Skip to content

Commit

Permalink
fix: add support to symbol type "REAL", "UINT"
Browse files Browse the repository at this point in the history
  • Loading branch information
randolfly committed Feb 17, 2025
1 parent f86d999 commit 75a5cad
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 13 deletions.
93 changes: 93 additions & 0 deletions src/TwincatToolbox/Extensions/SpanConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Text;

public static class SpanConverter
{
public static T ConvertTo<T>(ReadOnlySpan<byte> span) where T : struct {
if (span.Length < Marshal.SizeOf<T>())
{
throw new ArgumentException("The span is too small to contain the specified type.");
}

return MemoryMarshal.Read<T>(span);
}

public static object ConvertTo(ReadOnlySpan<byte> span, Type targetType) {
if (span == null || span.Length == 0)
{
throw new ArgumentException("Span is null or empty.", nameof(span));
}

if (targetType == null)
{
throw new ArgumentNullException(nameof(targetType));
}

switch (Type.GetTypeCode(targetType))
{
case TypeCode.Boolean:
if (span.Length >= sizeof(Boolean))
{
return BitConverter.ToBoolean(span);
}
break;
case TypeCode.UInt16:
if (span.Length >= sizeof(UInt16))
{
return BitConverter.ToUInt16(span);
}
break;
case TypeCode.UInt32:
if (span.Length >= sizeof(UInt32))
{
return BitConverter.ToUInt32(span);
}
break;
case TypeCode.UInt64:
if (span.Length >= sizeof(UInt64))
{
return BitConverter.ToUInt64(span);
}
break;
case TypeCode.Int16:
if (span.Length >= sizeof(Int16))
{
return BitConverter.ToInt16(span);
}
break;
case TypeCode.Int32:
if (span.Length >= sizeof(Int32))
{
return BitConverter.ToInt32(span);
}
break;
case TypeCode.Int64:
if (span.Length >= sizeof(Int64))
{
return BitConverter.ToInt64(span);
}
break;
case TypeCode.Single:
if (span.Length >= sizeof(Single))
{
return BitConverter.ToSingle(span);
}
break;
case TypeCode.Double:
if (span.Length >= sizeof(Double))
{
return BitConverter.ToDouble(span);
}
break;
// todo: add more cases
default:
throw new NotSupportedException($"Conversion to type '{targetType}' is not supported.");
}

throw new ArgumentException("Span does not contain enough data to convert to the specified type.", nameof(span));
}
}


1 change: 0 additions & 1 deletion src/TwincatToolbox/Models/SymbolInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

namespace TwincatToolbox.Models;

// todo: ¼ì²éÕâÀïµÄ partial classÊÇ·ñÓбØÒª
public class SymbolInfo(ISymbol symbol)
{
public ISymbol Symbol { get; set; } = symbol;
Expand Down
1 change: 1 addition & 0 deletions src/TwincatToolbox/TwincatToolbox.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationIcon>Assets\avalonia-logo.ico</ApplicationIcon>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
24 changes: 24 additions & 0 deletions src/TwincatToolbox/TwincatToolbox.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwincatToolbox", "TwincatToolbox.csproj", "{A0FF4E68-20C6-69CE-B6DD-17373783E8D5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0FF4E68-20C6-69CE-B6DD-17373783E8D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0FF4E68-20C6-69CE-B6DD-17373783E8D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0FF4E68-20C6-69CE-B6DD-17373783E8D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0FF4E68-20C6-69CE-B6DD-17373783E8D5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C31C6327-37C2-4E98-8910-E3603D16A755}
EndGlobalSection
EndGlobal
54 changes: 42 additions & 12 deletions src/TwincatToolbox/ViewModels/DataLogViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Timers;
using Avalonia.Controls;
Expand Down Expand Up @@ -238,20 +239,49 @@ private async Task StopLogAsync()
IsLoggingStopped = true;
}

private async void AdsNotificationHandler(object? sender, AdsNotificationEventArgs e)
{
double data = 0.0d;
data = e.Data.Length switch
// todo: fix extract type error, such as REAL(length = 4) => BinaryPrimitives.ReadHalfLittleEndian(e.Data.Span);
private async void AdsNotificationHandler(object? sender, AdsNotificationEventArgs e) {
if (!_symbolsDict.TryGetValue(e.Handle, out var symbol))
{
Debug.WriteLine("Symbol not found for handle: {0}", e.Handle);
return;
}

var dataType = (symbol.Symbol.DataType as DataType)?.ManagedType;
if (dataType == null)
{
Debug.WriteLine("ManagedType is null for symbol: {0}", symbol.Name);
return;
}

object data;
try
{
data = SpanConverter.ConvertTo(e.Data.Span, dataType);
}
catch (Exception ex)
{
Debug.WriteLine("Error converting data for symbol: {0}, Exception: {1}", symbol.Name, ex);
return;
}

double result = data switch
{
1 => BitConverter.ToBoolean(e.Data.Span) ? 1 : 0,
2 => BinaryPrimitives.ReadInt16LittleEndian(e.Data.Span),
4 => BinaryPrimitives.ReadInt32LittleEndian(e.Data.Span),
8 => BinaryPrimitives.ReadDoubleLittleEndian(e.Data.Span),
_ => 0
bool b => b ? 1.0 : 0.0,
byte b => b,
sbyte sb => sb,
short s => s,
ushort us => us,
int i => i,
uint ui => ui,
long l => l,
ulong ul => ul,
float f => f,
double d => d,
_ => throw new InvalidCastException($"Unsupported data type: {dataType}")
};
var symbol = _symbolsDict[e.Handle];

await _logDataService.AddDataAsync(symbol.Name, data);
_logPlotService.AddData(symbol.Name, data);
await _logDataService.AddDataAsync(symbol.Name, result);
_logPlotService.AddData(symbol.Name, result);
}
}

0 comments on commit 75a5cad

Please sign in to comment.