Skip to content

Commit

Permalink
better logging and stable connection
Browse files Browse the repository at this point in the history
- added extra logfile for observed variables
- added new observation of ads state
- re-organized connection cab
  • Loading branch information
fbarresi committed Jun 27, 2020
1 parent a7da620 commit 9ebf5a5
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 18 deletions.
13 changes: 10 additions & 3 deletions TwinCatAdsTool.Gui/ViewModels/ConnectionCabViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@

namespace TwinCatAdsTool.Gui.ViewModels
{
[SuppressMessage("ReSharper", "InvokeAsExtensionMethod")]
public class ConnectionCabViewModel : ViewModelBase
{
private readonly IClientService clientService;
private ObservableAsPropertyHelper<ConnectionState> connectionStateHelper;
private int port = 851;
private string selectedNetId;
private NetId selectedAmsNetId;
private ObservableAsPropertyHelper<string> adsStatusHelper;


public ConnectionCabViewModel(IClientService clientService)
Expand All @@ -40,7 +40,6 @@ public ConnectionCabViewModel(IClientService clientService)
public ConnectionState ConnectionState => connectionStateHelper.Value;
public ReactiveCommand<Unit, Unit> Disconnect { get; set; }


public int Port
{
get => port;
Expand Down Expand Up @@ -87,12 +86,17 @@ public override void Init()
.AddDisposableTo(Disposables).SetupErrorHandling(Logger, Disposables);
Disconnect = ReactiveCommand.CreateFromTask(DisconnectClient, canExecute: clientService.ConnectionState.Select(state => state == ConnectionState.Connected))
.AddDisposableTo(Disposables).SetupErrorHandling(Logger, Disposables);

connectionStateHelper = clientService
.ConnectionState
.ObserveOnDispatcher()
.ToProperty(this, model => model.ConnectionState);

adsStatusHelper = clientService
.AdsState
.ObserveOnDispatcher()
.ToProperty(this, model => model.AdsStatus);


AmsNetIds.AddRange(clientService.AmsNetIds);
AmsNetIds.Add(new NetId(){Address = "", Name = "*"});
Expand All @@ -103,8 +107,11 @@ public override void Init()
.Do(s => SelectedNetId = s.Address)
.Subscribe()
.AddDisposableTo(Disposables);

}

public string AdsStatus => adsStatusHelper.Value;

private async Task ConnectClient()
{
try
Expand Down
6 changes: 5 additions & 1 deletion TwinCatAdsTool.Gui/ViewModels/SymbolObservationViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using TwinCAT.TypeSystem;
using TwinCatAdsTool.Gui.Properties;
using TwinCatAdsTool.Interfaces.Extensions;
using TwinCatAdsTool.Interfaces.Logging;
using TwinCatAdsTool.Interfaces.Services;


Expand Down Expand Up @@ -43,8 +44,11 @@ public override void Init()
var readSymbolInfo = ClientService.Client.ReadSymbolInfo(Model.InstancePath);
var initialValue = ClientService.Client.ReadSymbol(readSymbolInfo);
var observable = ((IValueSymbol) Model).WhenValueChanged().StartWith(initialValue);

var obsLogger = LoggerFactory.GetObserverLogger();

observable.Do(value => Logger.Debug($"{FullName} value changed to: '{value}'"))
observable
.Do(value => obsLogger.Debug($"{FullName} value changed to: '{value}'"))
.Subscribe()
.AddDisposableTo(Disposables);

Expand Down
34 changes: 23 additions & 11 deletions TwinCatAdsTool.Gui/Views/ConnectionCabView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
xmlns:converters="clr-namespace:TwinCatAdsTool.Gui.Converters"
xmlns:properties="clr-namespace:TwinCatAdsTool.Gui.Properties"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
d:DesignHeight="350"
d:DesignWidth="1200">
<UserControl.Resources>
<converters:ConnectionStateToIconConverter x:Key="ConnectionStateToIconConverter" />
<converters:ConnectionStateToIsDisconnected x:Key="ConnectionStateToIsDisconnected" />
Expand All @@ -18,23 +19,34 @@
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" MinWidth="300"/>
<ColumnDefinition Width="Auto" MinWidth="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{x:Static properties:Resources.Address}" ContentStringFormat="{}{0}:" HorizontalContentAlignment="Right"/>
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static properties:Resources.Port}" ContentStringFormat="{}{0}:" HorizontalContentAlignment="Right"/>
<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding SelectedNetId, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Center" Padding="2"/>
<fa:ImageAwesome Grid.Row="2" Grid.Column="2" Icon="{Binding ConnectionState, Converter={StaticResource ConnectionStateToIconConverter}}" Width="20" HorizontalAlignment="Left"/>
<Label Grid.Row="1" Grid.Column="0" Content="ADS Id:" HorizontalContentAlignment="Right"/>
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static properties:Resources.Port}" ContentStringFormat="{}{0}:" HorizontalContentAlignment="Right"/>

<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding SelectedNetId, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Center" Padding="2"/>
<ComboBox ItemsSource="{Binding AmsNetIds}" SelectedValue="{Binding SelectedAmsNetId}" Grid.Row="0" Grid.Column="1" DisplayMemberPath="Name" IsEnabled="{Binding ConnectionState, Converter={StaticResource ConnectionStateToIsDisconnected}}" />
<TextBox Text="{Binding Port}" Grid.Row="1" Grid.Column="1" />
<Button Grid.Row="2" Grid.Column="0" Command="{Binding Connect}" Content="{x:Static properties:Resources.Connect}"/>
<Button Grid.Row="2" Grid.Column="1" Command="{Binding Disconnect}" Content="{x:Static properties:Resources.Disconnect}"/>
<TextBox Text="{Binding Port}" Grid.Row="2" Grid.Column="1" />

<Button Grid.Row="3" Grid.Column="0" Command="{Binding Connect}" Content="{x:Static properties:Resources.Connect}"/>
<Button Grid.Row="3" Grid.Column="1" Command="{Binding Disconnect}" Content="{x:Static properties:Resources.Disconnect}"/>

<Grid Grid.Row="1" Grid.Column="2" Grid.RowSpan="2" Grid.ColumnSpan="2">
<Grid Grid.Row="3" Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" Icon="{Binding ConnectionState, Converter={StaticResource ConnectionStateToIconConverter}}" Width="20" HorizontalAlignment="Left"/>
<Label Grid.Column="1" Content="{Binding AdsStatus}"/>
</Grid>
<Grid Grid.Row="0" Grid.Column="2" Grid.RowSpan="3">
<Image Source="../Resources/evopro.png" Width="300" MouseDown="UIElement_OnMouseDown"/>
<Label Content="{x:Static properties:Resources.PoweredBy}"/>
</Grid>
Expand Down
1 change: 1 addition & 0 deletions TwinCatAdsTool.Interfaces/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ namespace TwinCatAdsTool.Interfaces
public static class Constants
{
public const string LoggingRepositoryName = "TwinCatAdsTool";
public const string LoggingObservationRepositoryName = "observation";
}
}
5 changes: 5 additions & 0 deletions TwinCatAdsTool.Interfaces/Logging/LoggerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ public static ILog GetLogger()
{
return LogManager.GetLogger(Constants.LoggingRepositoryName);
}

public static ILog GetObserverLogger()
{
return LogManager.GetLogger(Constants.LoggingObservationRepositoryName);
}
}
}
1 change: 1 addition & 0 deletions TwinCatAdsTool.Interfaces/Services/IClientService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public interface IClientService
Task Connect(string amsNetId, int port);
TcAdsClient Client { get; }
IObservable<ConnectionState> ConnectionState { get; }
IObservable<string> AdsState { get; }
ReadOnlySymbolCollection TreeViewSymbols { get; }
ReadOnlySymbolCollection FlatViewSymbols { get; }
List<NetId> AmsNetIds { get; set; }
Expand Down
54 changes: 52 additions & 2 deletions TwinCatAdsTool.Logic/Services/ClientService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
using System.Reactive.Subjects;
using System.Threading.Tasks;
using System.Windows.Forms;
using Humanizer;
using log4net;
using Ninject;
using TwinCAT;
using TwinCAT.Ads;
using TwinCAT.Ads.TypeSystem;
using TwinCAT.TypeSystem;
using TwinCatAdsTool.Interfaces.Extensions;
using TwinCatAdsTool.Interfaces.Logging;
using TwinCatAdsTool.Interfaces.Models;
using TwinCatAdsTool.Interfaces.Services;
using TwinCatAdsTool.Logic.Properties;
Expand All @@ -28,24 +31,35 @@ public class ClientService : IClientService, IInitializable, IDisposable
{
private readonly BehaviorSubject<ConnectionState> connectionStateSubject = new BehaviorSubject<ConnectionState>(TwinCAT.ConnectionState.Unknown);
private readonly CompositeDisposable disposables = new CompositeDisposable();
private readonly BehaviorSubject<string> adsStateSubject = new BehaviorSubject<string>(TwinCAT.Ads.AdsState.Idle.ToString());
private readonly ILog logger = LoggerFactory.GetLogger();
public ClientService()
{
Client = new TcAdsClient();

}

public bool ConnectionStarted { get; set; }

public string CurrentAmsNetId { get; set; }
public int CurrentPort { get; set; }

public Task Connect(string amsNetId, int port)
{
CurrentPort = port;
CurrentAmsNetId = amsNetId;
if (!Client.IsConnected)
{
Client.Connect(amsNetId, port);
}

ConnectionStarted = true;
return Task.FromResult(Unit.Default);
}

public TcAdsClient Client { get; }
public IObservable<ConnectionState> ConnectionState => connectionStateSubject.AsObservable();
public IObservable<string> AdsState => adsStateSubject.AsObservable();
public ReadOnlySymbolCollection TreeViewSymbols { get; set; }
public ReadOnlySymbolCollection FlatViewSymbols { get; set; }
public List<NetId> AmsNetIds { get; set; }
Expand All @@ -57,24 +71,32 @@ public Task Reload()
public Task Disconnect()
{
Client.Disconnect();
ConnectionStarted = false;
adsStateSubject.OnNext(TwinCAT.Ads.AdsState.Idle.ToString());
return Task.FromResult(Unit.Default);
}

public void Initialize()
{
Observable.FromEventPattern<ConnectionStateChangedEventArgs>(ev => Client.ConnectionStateChanged += ev,
ev => Client.ConnectionStateChanged -= ev)
ev => Client.ConnectionStateChanged -= ev)
.Select(pattern => pattern.EventArgs.NewState)
.Subscribe(connectionStateSubject.OnNext)
.AddDisposableTo(disposables);

connectionStateSubject
.DistinctUntilChanged()
.Where(state => state == TwinCAT.ConnectionState.Connected)
.Do(UpdateSymbols)
.Subscribe()
.AddDisposableTo(disposables);

Observable.Interval(TimeSpan.FromSeconds(1))
.ObserveOnDispatcher()
.Do(_ => CheckConnectionHealth())
.Subscribe()
.AddDisposableTo(disposables);

IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());

var localhost = host
Expand All @@ -99,6 +121,34 @@ private void UpdateSymbols(ConnectionState state)
}
}

private void CheckConnectionHealth()
{
try
{
if (ConnectionStarted)
{
if (!Client.IsConnected)
{
Client.Connect(CurrentAmsNetId, CurrentPort);
}
else
connectionStateSubject.OnNext(TwinCAT.ConnectionState.Connected);

var state = Client.ReadState();
adsStateSubject.OnNext(state.AdsState.ToString());
}
}
catch (AdsErrorException e)
{
adsStateSubject.OnNext(TwinCAT.Ads.AdsState.Invalid+" - "+e.ErrorCode.Humanize());

if (!Client.IsConnected)
{
connectionStateSubject.OnNext(TwinCAT.ConnectionState.Lost);
Client.Disconnect();
}
}
}

public void Dispose()
{
Expand Down
1 change: 1 addition & 0 deletions TwinCatAdsTool.Logic/TwinCatAdsTool.Logic.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

<ItemGroup>
<PackageReference Include="Beckhoff.TwinCAT.Ads.Reactive" Version="4.3.10" />
<PackageReference Include="Humanizer" Version="2.8.26" />
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="System.Reactive" Version="4.1.3" />
Expand Down
1 change: 1 addition & 0 deletions TwinCatAdsTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private static void CreateLogger()
{
log4net.Config.XmlConfigurator.Configure(new FileInfo("log.config"));
LogManager.CreateRepository(Constants.LoggingRepositoryName);
LogManager.CreateRepository(Constants.LoggingObservationRepositoryName);
}

private static void LoadModules(IKernel kernel)
Expand Down
23 changes: 22 additions & 1 deletion TwinCatAdsTool/log.config
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,32 @@
<levelMin value="DEBUG" />
</filter>
</appender>

<appender name="ObsRollingFile" type="log4net.Appender.RollingFileAppender">
<file value="logs\TwinCatAdsTool.Observation.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<encoding value="utf-8" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date{dd.MM. HH:mm:ss.fff}] %-5level - %C{1}.%M - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="TRACE" />
</filter>
</appender>

<root>
<root>
<level value="ALL" />
<appender-ref ref="RollingFile" />
</root>

<logger name="observation">
<level value="ALL"/>
<appender-ref ref="ObsRollingFile" />
</logger>
</log4net>

</configuration>

0 comments on commit 9ebf5a5

Please sign in to comment.