Skip to content

Commit

Permalink
Merge pull request #8 from WildernessLabs/develop
Browse files Browse the repository at this point in the history
Merge to main for RC2-2
  • Loading branch information
jorgedevs authored Mar 5, 2023
2 parents 175950a + e97ec6c commit 305c73a
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 29 deletions.
6 changes: 5 additions & 1 deletion src/Meadow.Modbus.Unit.Tests/ModbusSerialTStatTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public async void OverlappingAccessTest()
{
ushort sp = 600;

for(int i = 0; i < 10; i++)
for (int i = 0; i < 10; i++)
{
Debug.WriteLine("-->");
await client.WriteHoldingRegister(address, setpointRegister, sp);
Expand Down Expand Up @@ -121,6 +121,10 @@ public async void ReadHoldingRegisterTest()
var readCount = 1;

var client = new ModbusRtuClient(port);
{
// force meadow to compile the serial stuff
};

var r1 = await client.ReadHoldingRegisters(address, startRegister, readCount);
Assert.Equal(readCount, r1.Length);

Expand Down
51 changes: 50 additions & 1 deletion src/Meadow.Modbus.Unit.Tests/ModbusTcpLoopbackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public async void ReadMultipleHoldingRegistersLoopbackTest()
{
callbackOccurred = false;

testRegisterAddress = (ushort)r.Next(ushort.MaxValue);
testRegisterAddress = (ushort)r.Next(9999);
var result = await client.ReadHoldingRegisters(255, testRegisterAddress, r.Next(2, 21));

Assert.True(callbackOccurred);
Expand Down Expand Up @@ -225,5 +225,54 @@ public async void ReadCoilsLoopbackTest()
}
}
}

[Fact]
public async void ReadMultipleInputRegistersLoopbackTest()
{
ushort[]? testData = null;
ushort testRegisterAddress = 42;
bool callbackOccurred = false;
var r = new Random();

using (var server = new ModbusTcpServer(502))
using (var client = new ModbusTcpClient("127.0.0.1"))
{
server.ReadInputRegisterRequest += (address, count) =>
{
Assert.Equal(testRegisterAddress, address);

// generate some new random data - the request is for registers, which are ushorts
testData = new ushort[count];
for (int i = 0; i < testData.Length; i++)
{
testData[i] = (ushort)r.Next(ushort.MaxValue);
}

callbackOccurred = true;
return new ModbusReadResult(testData);
};

server.Start();

await client.Connect();

// loop for 5 reads - reading 1-16 coils
// the event handler above checks the result
for (int i = 0; i < 5; i++)
{
testRegisterAddress = (ushort)r.Next(9999); // register range is only 10k
var result = await client.ReadInputRegisters(255, testRegisterAddress, r.Next(1, 17));
Assert.True(callbackOccurred);
Assert.NotNull(testData);
Assert.NotNull(result);
Assert.Equal(testData?.Length, result.Length);

for (int index = 0; index < testData?.Length; index++)
{
Assert.Equal(testData[index], result[index]);
}
}
}
}
}
}
17 changes: 13 additions & 4 deletions src/Meadow.Modbus/Clients/ModbusRtuClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ private void SetEnable(bool state)
}
}

protected Action? PostOpenAction { get; set; } = null;
protected Action<byte[]>? PostWriteDelayAction { get; set; } = null;

public override Task Connect()
{
SetEnable(false);
Expand All @@ -49,6 +52,8 @@ public override Task Connect()
{
_port.Open();
_port.ClearReceiveBuffer();

PostOpenAction?.Invoke();
}

_byteTime = (1d / _port.BaudRate) * _port.DataBits * 1000d;
Expand Down Expand Up @@ -125,7 +130,7 @@ protected override async Task<byte[]> ReadResult(ModbusFunction function)
var actualCrc = buffer[buffer.Length - 2] | buffer[buffer.Length - 1] << 8;
if (expectedCrc != actualCrc) { throw new CrcException(); }

if(resultLen == 0)
if (resultLen == 0)
{ //happens on write multiples
return new byte[0];
}
Expand All @@ -136,15 +141,19 @@ protected override async Task<byte[]> ReadResult(ModbusFunction function)
return await Task.FromResult(result);
}

protected override async Task DeliverMessage(byte[] message)
protected override Task DeliverMessage(byte[] message)
{
SetEnable(true);

_port.Write(message);
// the above call to the OS transfers data to the serial buffer - it does *not* mean all data has gone out on the wire
// we must wait for all data to get transmitted before lowering the enable line
var wait = (int)(_byteTime * message.Length) + 1;
await Task.Delay(wait);

PostWriteDelayAction?.Invoke(message);

SetEnable(false);

return Task.CompletedTask;
}

protected override byte[] GenerateReadMessage(byte modbusAddress, ModbusFunction function, ushort startRegister, int registerCount)
Expand Down
9 changes: 6 additions & 3 deletions src/Meadow.Modbus/Meadow.Modbus.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
Expand All @@ -16,10 +16,13 @@

<ItemGroup>
<None Include="icon.png" Pack="true" PackagePath="" />
<PackageReference Include="Meadow.Contracts" Version="0.94.1" />
<PackageReference Include="Meadow.Logging" Version="0.92.5" />
<PackageReference Include="System.IO.Ports" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Meadow.Contracts" Version="0.*" />
<PackageReference Include="Meadow.Logging" Version="0.*" />
</ItemGroup>


</Project>
23 changes: 3 additions & 20 deletions src/samples/F7v2RtuSample/MeadowApp.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Meadow;
using Meadow.Devices;
using Meadow.Hardware;
using Meadow.Modbus;
using System;
using System.Threading.Tasks;
Expand All @@ -10,30 +9,14 @@ namespace F7v2RtuSample
public class MeadowApp : App<F7FeatherV2>
{
private ModbusRtuClient _client;
private ProjectLab _board;

public override Task Initialize()
{
Resolver.Log.Info("Initialize hardware...");

var port = Device.CreateSerialPort(Device.SerialPortNames.Com4, 19200, 8, Meadow.Hardware.Parity.None, Meadow.Hardware.StopBits.One);
port.WriteTimeout = port.ReadTimeout = TimeSpan.FromSeconds(5);

var projLab = new ProjectLab();
IDigitalOutputPort serialEnable;

if (projLab.IsV1Hardware())
{
Resolver.Log.Info("ProjectLab v1 detected");
serialEnable = Device.CreateDigitalOutputPort(Device.Pins.D09, false); // early ProjLab and Hack board
}
else
{
Resolver.Log.Info("ProjectLab v2 detected");
serialEnable = projLab.Mcp_2.CreateDigitalOutputPort(projLab.Mcp_2.Pins.GP0, false);
}

Resolver.Log.Info("Creating the Modbus RTU Enable port");
_client = new ModbusRtuClient(port, serialEnable);
_board = new ProjectLab();
_client = _board.GetModbusRtuClient(19200);

return Task.CompletedTask;
}
Expand Down

0 comments on commit 305c73a

Please sign in to comment.