Skip to content

Commit

Permalink
Generized memory areas
Browse files Browse the repository at this point in the history
  • Loading branch information
Sandoun committed Aug 8, 2023
1 parent 5ed2580 commit a06a69b
Show file tree
Hide file tree
Showing 25 changed files with 526 additions and 299 deletions.
1 change: 1 addition & 0 deletions Examples.WPF/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
StartupUri="MainWindow.xaml">
<Application.Resources>
<conv:NegationConverter x:Key="bInv"/>
<conv:ColorHashConverter x:Key="hashColor"/>
</Application.Resources>
</Application>
62 changes: 62 additions & 0 deletions Examples.WPF/Converters/ColorHashConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Drawing;
using System.Globalization;
using System.Windows.Data;


namespace Examples.WPF.Converters;

[ValueConversion(typeof(bool), typeof(bool))]
public class ColorHashConverter : IValueConverter {

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {

var hashCode = value.GetHashCode();
var randColor = GenerateRandomVibrantColor(new Random(hashCode));

System.Windows.Media.Brush outBrush = new System.Windows.Media.SolidColorBrush(new System.Windows.Media.Color {
R = randColor.R,
G = randColor.G,
B = randColor.B,
A = 255,
});

return outBrush;

}

private Color GenerateRandomVibrantColor(Random random) {

byte red = (byte)random.Next(256);
byte green = (byte)random.Next(256);
byte blue = (byte)random.Next(256);

Color color = Color.FromArgb(255, red, green, blue);

// Ensure the color is vibrant and colorful
while (!IsVibrantColor(color)) {
red = (byte)random.Next(256);
green = (byte)random.Next(256);
blue = (byte)random.Next(256);
color = Color.FromArgb(255,red, green, blue);
}

return color;
}

private bool IsVibrantColor(Color color) {

int minBrightness = 100;
int maxBrightness = 200;
int minSaturation = 150;

int brightness = (int)(color.GetBrightness() * 255);
int saturation = (int)(color.GetSaturation() * 255);

return brightness >= minBrightness && brightness <= maxBrightness && saturation >= minSaturation;

}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();

}
19 changes: 19 additions & 0 deletions Examples.WPF/ViewModels/PlcDataViewViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MewtocolNet;
using MewtocolNet.Events;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,6 +10,24 @@ namespace Examples.WPF.ViewModels;

public class PlcDataViewViewModel : ViewModelBase {

private ReconnectArgs plcCurrentReconnectArgs = null!;

public IPlc Plc => App.ViewModel.Plc!;

public ReconnectArgs PlcCurrentReconnectArgs {
get => plcCurrentReconnectArgs;
set {
plcCurrentReconnectArgs = value;
OnPropChange();
}
}

public PlcDataViewViewModel () {

Plc.ReconnectTryStarted += (s, e) => PlcCurrentReconnectArgs = e;
Plc.Reconnected += (s, e) => PlcCurrentReconnectArgs = null!;
Plc.Disconnected += (s, e) => PlcCurrentReconnectArgs = null!;

}

}
7 changes: 6 additions & 1 deletion Examples.WPF/Views/ConnectView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ private void ClickedConnectEth(object sender, RoutedEventArgs e) {
App.ViewModel.Plc = Mewtocol.Ethernet(viewModel.SelectedIP, parsedInt)
.WithPoller()
.WithInterfaceSettings(setting => {
setting.TryReconnectAttempts = 30;
setting.TryReconnectAttempts = 0;
setting.TryReconnectDelayMs = 2000;
setting.SendReceiveTimeoutMs = 1000;
setting.HeartbeatIntervalMs = 3000;
setting.MaxDataBlocksPerWrite = 12;
setting.MaxOptimizationDistance = 10;
})
.WithCustomPollLevels(lvl => {
lvl.SetLevel(2, 3);
Expand All @@ -73,6 +76,8 @@ private void ClickedConnectEth(object sender, RoutedEventArgs e) {
//b.Struct<short>("DT0").Build();
//b.Struct<short>("DT0").AsArray(30).Build();
b.Bool("R10A").Build();
b.Struct<short>("DT1000").Build(out heartbeatSetter);
b.Struct<Word>("DT1000").Build();
Expand Down
68 changes: 67 additions & 1 deletion Examples.WPF/Views/PlcDataView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,56 @@
<StackPanel Margin="10"
Grid.Row="1">

<TextBlock>
<TextBlock IsEnabled="{Binding Plc.IsConnected}">

<Run Text="{Binding Plc.PlcInfo.TypeName, Mode=OneWay}"
FontSize="24"
BaselineAlignment="Center"
FontWeight="SemiBold"/>

<Run Text="{Binding Plc.PlcInfo.CpuVersion, StringFormat='v{0}', Mode=OneWay}"
FontSize="24"
FontWeight="Light"/>

<Ellipse Width="10"
Height="10"
Fill="Lime"
IsEnabled="{Binding Plc.IsConnected}"/>

<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

</TextBlock>

<TextBlock IsEnabled="{Binding Plc.IsConnected, Converter={StaticResource bInv}}">

<Run Text="Disconnected"
FontSize="24"
BaselineAlignment="Center"
FontWeight="SemiBold"/>

<Ellipse Width="10"
Height="10"
Fill="Red"
IsEnabled="{Binding Plc.IsConnected}"/>

<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

</TextBlock>

<TextBlock Text="{Binding Plc.PlcInfo.TypeCode, StringFormat='#{0:X}', Mode=OneWay}"
Expand Down Expand Up @@ -84,6 +124,25 @@
</ItemsControl.ItemTemplate>
</ItemsControl>

<TextBlock>

<Run Text="Reconnecting..."/>
<Run Text="{Binding PlcCurrentReconnectArgs.ReconnectTry, Mode=OneWay, StringFormat='{}{0}/'}"/>
<Run Text="{Binding PlcCurrentReconnectArgs.MaxAttempts, Mode=OneWay}"/> in
<Run Text="{Binding PlcCurrentReconnectArgs.RetryCountDownRemaining, Mode=OneWay}"/>

<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding PlcCurrentReconnectArgs, Mode=OneWay}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

</TextBlock>

</StackPanel>

<DataGrid Grid.Row="2"
Expand All @@ -96,6 +155,13 @@
<DataGridTextColumn Header="Value" Binding="{Binding ValueStr}"/>
<DataGridTextColumn Header="Poll Level" Binding="{Binding PollLevel, Mode=OneWay}"/>
<DataGridTextColumn Header="Update Frequency" Binding="{Binding UpdateFreqHz, StringFormat='{}{0} Hz',Mode=OneWay}"/>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border Background="{Binding MemoryAreaHash, Mode=OneWay, Converter={StaticResource hashColor}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

Expand Down
84 changes: 84 additions & 0 deletions MewtocolNet/Events/ReconnectArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using MewtocolNet.Registers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;

namespace MewtocolNet.Events {

public delegate void PlcReconnectEventHandler(object sender, ReconnectArgs e);

public class ReconnectArgs : EventArgs, INotifyPropertyChanged {

private TimeSpan retryCountDownRemaining;

public event PropertyChangedEventHandler PropertyChanged;

public int ReconnectTry { get; internal set; }

public int MaxAttempts { get; internal set; }

public TimeSpan RetryCountDownTime { get; internal set; }

public TimeSpan RetryCountDownRemaining {
get => retryCountDownRemaining;
private set {
retryCountDownRemaining = value;
OnPropChange();
}
}

private System.Timers.Timer countDownTimer;

internal ReconnectArgs(int currentAttempt, int totalAttempts, TimeSpan delayBetween) {

ReconnectTry = currentAttempt;
MaxAttempts = totalAttempts;
RetryCountDownTime = delayBetween;

//start countdown timer
RetryCountDownRemaining = RetryCountDownTime;

var interval = 100;
var intervalTS = TimeSpan.FromMilliseconds(interval);

countDownTimer = new System.Timers.Timer(100);

countDownTimer.Elapsed += (s, e) => {
if (RetryCountDownRemaining <= TimeSpan.Zero) {
StopTimer();
return;
}
RetryCountDownRemaining -= intervalTS;
};

countDownTimer.Start();

}

internal void ConnectionSuccess () {

StopTimer();

}

private void StopTimer () {

countDownTimer?.Stop();
RetryCountDownRemaining = TimeSpan.Zero;

}

private void OnPropChange([CallerMemberName] string propertyName = null) {

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

}

}

}
17 changes: 17 additions & 0 deletions MewtocolNet/Helpers/MewtocolHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ public static class MewtocolHelpers {

#region Byte and string operation helpers

public static T SetFlag<T>(this Enum value, T flag, bool set) {

Type underlyingType = Enum.GetUnderlyingType(value.GetType());

dynamic valueAsInt = Convert.ChangeType(value, underlyingType);
dynamic flagAsInt = Convert.ChangeType(flag, underlyingType);

if (set) {
valueAsInt |= flagAsInt;
} else {
valueAsInt &= ~flagAsInt;
}

return (T)valueAsInt;

}

public static int DetermineTypeByteIntialSize(this Type type) {

//enums can only be of numeric types
Expand Down
28 changes: 27 additions & 1 deletion MewtocolNet/IPlc.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MewtocolNet.ProgramParsing;
using MewtocolNet.Events;
using MewtocolNet.ProgramParsing;
using MewtocolNet.RegisterBuilding;
using MewtocolNet.Registers;
using System;
Expand All @@ -12,6 +13,31 @@ namespace MewtocolNet {
/// Provides a interface for Panasonic PLCs
/// </summary>
public interface IPlc : IDisposable, INotifyPropertyChanged {

/// <summary>
/// Fires when the interface is fully connected to a PLC
/// </summary>
event PlcConnectionEventHandler Connected;

/// <summary>
/// Fires when a reconnect attempt was successfull
/// </summary>
event PlcConnectionEventHandler Reconnected;

/// <summary>
/// Fires when the interfaces makes a reconnect try to the PLC
/// </summary>
event PlcReconnectEventHandler ReconnectTryStarted;

/// <summary>
/// Fires when the plc/interface connection was fully closed
/// </summary>
event PlcConnectionEventHandler Disconnected;

/// <summary>
/// Fires when the value of a register changes
/// </summary>
event RegisterChangedEventHandler RegisterChanged;

/// <summary>
/// The current connection state of the interface
Expand Down
Loading

0 comments on commit a06a69b

Please sign in to comment.