Skip to content

Commit

Permalink
Merge pull request #50 from WildernessLabs/bug/fixes
Browse files Browse the repository at this point in the history
fixes and improvements
  • Loading branch information
ctacke authored Nov 19, 2024
2 parents e3587d6 + 9685b2f commit f228a4a
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 11 deletions.
10 changes: 5 additions & 5 deletions src/Meadow.Modbus.Unit.Tests/Meadow.Modbus.Unit.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="System.IO.Ports" Version="6.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="System.IO.Ports" Version="9.0.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
36 changes: 35 additions & 1 deletion src/Meadow.Modbus/Clients/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public static class Extensions
/// Converts a set of Modbus registers (ushort[]) to integers (int[]) assuming little-endina ordering
/// </summary>
/// <param name="registers"></param>
/// <returns></returns>
public static int[] ConvertRegistersToInt32(this ushort[] registers)
{
var values = new int[registers.Length / 2];
Expand All @@ -28,6 +27,17 @@ public static int[] ConvertRegistersToInt32(this ushort[] registers)
return values;
}

/// <summary>
/// Converts ushort registers to a single Int32, starting at a specific offset
/// </summary>
/// <param name="registers">The registers</param>
/// <param name="startOffset">The offset in the registers to begine extraction</param>
/// <param name="swappedWords">True to convert from big-endian words</param>
public static int ExtractInt32(this ushort[] registers, int startOffset = 0, bool swappedWords = false)
{
return registers.AsSpan().ExtractInt32(startOffset, swappedWords);
}

/// <summary>
/// Converts ushort registers to a single Int32, starting at a specific offset
/// </summary>
Expand Down Expand Up @@ -140,6 +150,17 @@ public static ulong ExtractUInt64(this Span<ushort> registers, int startOffset =
}
}

/// <summary>
/// Converts 4 ushort registers to a IEEE 64 floating point, starting at a specific offset
/// </summary>
/// <param name="registers">The registers</param>
/// <param name="startOffset">The offset in the registers to begine extraction</param>
/// <param name="swappedWords">True to convert from big-endian words</param>
public static double ExtractDouble(this ushort[] registers, int startOffset = 0, bool swappedWords = false)
{
return registers.AsSpan().ExtractDouble(startOffset, swappedWords);
}

/// <summary>
/// Converts 4 ushort registers to a IEEE 64 floating point, starting at a specific offset
/// </summary>
Expand All @@ -148,6 +169,8 @@ public static ulong ExtractUInt64(this Span<ushort> registers, int startOffset =
/// <param name="swappedWords">True to convert from big-endian words</param>
public static double ExtractDouble(this Span<ushort> registers, int startOffset = 0, bool swappedWords = false)
{
if (registers.Length < 4) throw new ArgumentException("registers does not contain enough data to extract a double");

if (swappedWords)
{
byte[] value = BitConverter.GetBytes(registers[startOffset + 0])
Expand All @@ -170,6 +193,17 @@ public static double ExtractDouble(this Span<ushort> registers, int startOffset
}
}

/// <summary>
/// Converts 2 ushort registers to a IEEE 32 floating point, starting at a specific offset
/// </summary>
/// <param name="registers">The registers</param>
/// <param name="startOffset">The offset in the registers to begine extraction</param>
/// <param name="swappedWords">True to convert from big-endian words</param>
public static float ExtractSingle(this ushort[] registers, int startOffset = 0, bool swappedWords = false)
{
return registers.AsSpan().ExtractSingle(startOffset, swappedWords);
}

/// <summary>
/// Converts 2 ushort registers to a IEEE 32 floating point, starting at a specific offset
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Meadow.Modbus/Clients/ModbusRtuClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ protected override async Task<byte[]> ReadResult(ModbusFunction function)

switch (function)
{
case ModbusFunction.WriteMultipleRegisters:
case ModbusFunction.WriteRegister:
case ModbusFunction.WriteMultipleCoils:
case ModbusFunction.WriteCoil:
bufferLen = 8; //fixed length
resultLen = 0; //no result data
break;
case ModbusFunction.WriteRegister:
case ModbusFunction.WriteMultipleRegisters:
bufferLen = 7 + header[headerLen - 1];
resultLen = header[2];
break;
Expand Down
2 changes: 1 addition & 1 deletion src/Meadow.Modbus/Meadow.Modbus.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</PropertyGroup>
<ItemGroup>
<None Include="icon.png" Pack="true" PackagePath="" />
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
<PackageReference Include="System.IO.Ports" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Meadow.Contracts\Source\Meadow.Contracts\Meadow.Contracts.csproj" />
Expand Down
41 changes: 39 additions & 2 deletions src/Meadow.Modbus/ModbusPolledDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public abstract class ModbusPolledDevice
/// </summary>
public event EventHandler<Exception>? CommError;

/// <summary>
/// Raised when data has been read from the device
/// </summary>
public event EventHandler? DataUpdated;

/// <summary>
/// Represents the possible formats of source registers
/// </summary>
Expand Down Expand Up @@ -83,7 +88,8 @@ private class RegisterMapping
/// </summary>
public virtual void StartPolling()
{
_timer.Change(_refreshPeriosMs, -1);
// trigger first read immediately - subsequent reads will be at the desired frequency
_timer.Change(0, -1);
}

/// <summary>
Expand Down Expand Up @@ -126,6 +132,17 @@ protected async Task WriteHoldingRegister(ushort startRegister, params ushort[]
}
}

/// <summary>
/// Writes one or more values to the holding registers of the Modbus device.
/// </summary>
/// <param name="startRegister">The starting register address.</param>
/// <param name="count">The number of registers to read.</param>
/// <returns>A task representing the asynchronous write operation.</returns>
protected Task<ushort[]> ReadHoldingRegisters(ushort startRegister, int count)
{
return _client.ReadHoldingRegisters(_address, startRegister, count);
}

/// <summary>
/// Reads a value from a coil register of the Modbus device.
/// </summary>
Expand Down Expand Up @@ -361,6 +378,8 @@ private async void RefreshTimerProc(object _)
{
await MoveHoldingRegistersToProperties();
await MoveInputRegistersToProperties();

DataUpdated?.Invoke(this, EventArgs.Empty);
}
finally
{
Expand Down Expand Up @@ -517,17 +536,27 @@ private void UpdateField(ushort[] data, RegisterMapping mapping)
}
else if (
mapping.FieldInfo!.FieldType == typeof(byte) ||
mapping.FieldInfo!.FieldType == typeof(ushort) ||
mapping.FieldInfo!.FieldType == typeof(short) ||
mapping.FieldInfo!.FieldType == typeof(int) ||
mapping.FieldInfo!.FieldType == typeof(uint) ||
mapping.FieldInfo!.FieldType == typeof(long))
{
UpdateIntegerField(data, mapping);
}
else if (
mapping.PropertyInfo!.PropertyType == typeof(bool))
mapping.FieldInfo!.FieldType == typeof(bool))
{
UpdateBooleanField(data, mapping);
}
else if (
mapping.FieldInfo!.FieldType == typeof(ushort[]) ||
mapping.FieldInfo!.FieldType == typeof(short[]))
{
// the field is a ref value, so this is valid
ushort[] f = (ushort[])mapping.FieldInfo.GetValue(this);
Array.Copy(data, f, Math.Min(data.Length, f.Length));
}
else
{
throw new NotSupportedException();
Expand Down Expand Up @@ -670,10 +699,18 @@ private void UpdateIntegerField(ushort[] data, RegisterMapping mapping)
{
mapping.FieldInfo!.SetValue(this, Convert.ToInt16(final));
}
else if (mapping.FieldInfo!.FieldType == typeof(ushort))
{
mapping.FieldInfo!.SetValue(this, Convert.ToUInt16(final));
}
else if (mapping.FieldInfo!.FieldType == typeof(int))
{
mapping.FieldInfo!.SetValue(this, Convert.ToInt32(final));
}
else if (mapping.FieldInfo!.FieldType == typeof(uint))
{
mapping.FieldInfo!.SetValue(this, Convert.ToUInt32(final));
}
else if (mapping.FieldInfo!.FieldType == typeof(long))
{
mapping.FieldInfo!.SetValue(this, final);
Expand Down

0 comments on commit f228a4a

Please sign in to comment.