Skip to content

Commit

Permalink
Merge pull request #38 from Apollo3zehn/dev
Browse files Browse the repository at this point in the history
Prepare 2.3.0.
  • Loading branch information
Apollo3zehn authored Nov 6, 2020
2 parents ca56ca4 + d5f000f commit a9478dd
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 105 deletions.
4 changes: 2 additions & 2 deletions build/build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

<PropertyGroup>
<Major Condition="$(Major) == ''">2</Major>
<Minor Condition="$(Minor) == ''">2</Minor>
<Revision Condition="$(Revision) == ''">1</Revision>
<Minor Condition="$(Minor) == ''">3</Minor>
<Revision Condition="$(Revision) == ''">0</Revision>
<VersionSuffix Condition="$(VersionSuffix) == ''"></VersionSuffix>
</PropertyGroup>

Expand Down
41 changes: 22 additions & 19 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ float[] floatArray = floatSpan.ToArray();
First, define the unit identifier, the starting address and the number of values to read (count):

```cs
var unitIdentifier = (byte)0xFF; // 0x00 and 0xFF are the defaults for TCP/IP-only Modbus devices.
var startingAddress = (ushort)0;
var count = (ushort)10;
var unitIdentifier = 0xFF; // 0x00 and 0xFF are the defaults for TCP/IP-only Modbus devices.
var startingAddress = 0;
var count = 10;
```

Then, read the data:
Expand Down Expand Up @@ -158,7 +158,7 @@ async byte[] DoAsync()

await <awaitsomething>;

return client.ReadHoldingRegisters(1, 2, 3).ToArray();
return client.ReadHoldingRegisters<float>(1, 2, 3).ToArray();
}
```

Expand All @@ -169,9 +169,9 @@ async byte[] DoAsync()
Boolean values are returned as single bits (1 = true, 0 = false), which are packed into bytes. If you request 10 booleans you get a ```Span<byte>``` in return with a length of ```2``` bytes. In this example, the remaining ```6``` bits are fill values.

```cs
var unitIdentifier = (byte)0xFF;
var startingAddress = (ushort)0;
var quantity = (ushort)10;
var unitIdentifier = 0xFF;
var startingAddress = 0;
var quantity = 10;

var boolData = client.ReadCoils(unitIdentifier, startingAddress, quantity);
```
Expand All @@ -192,10 +192,10 @@ See also [this](https://stackoverflow.com/questions/47981/how-do-you-set-clear-a
The following example shows how to write the number ```4263``` to the server:

```cs
var unitIdentifier = (byte)0xFF;
var startingAddress = (ushort)0;
var registerAddress = (ushort)0;
var quantity = (ushort)10;
var unitIdentifier = 0xFF;
var startingAddress = 0;
var registerAddress = 0;
var quantity = 10;

var shortData = new short[] { 4263 };
client.WriteSingleRegister(unitIdentifier, registerAddress, shortData);
Expand All @@ -207,7 +207,7 @@ Console.WriteLine(shortDataResult[0]); // should print '4263'

> **Note**: The Modbus protocol defines a basic register size of 2 bytes. Thus, the write methods require input values (or arrays) with even number of bytes (2, 4, 6, ...). This means that a call to ```client.WriteSingleRegister(0, 0, new byte { 1 })``` will not work, but ```client.WriteSingleRegister(0, 0, new short { 1 })``` will do. Since the client validates all your inputs (and so the server does), you will get notified if anything is wrong.
If you want to write float values, the procedure is the same as shown previously using the generic overload:
If you want to write `float` values, the procedure is the same as shown previously using the generic overload:

```cs
var floatData = new float[] { 1.1F, 9557e3F };
Expand Down Expand Up @@ -250,16 +250,17 @@ server.Start();

while (!cts.IsCancellationRequested)
{
var intData = server.GetHoldingRegisterBuffer<int>();
var registers = server.GetHoldingRegisters();

// lock is required to synchronize buffer access between
// this application and one or more Modbus clients
lock (server.Lock)
{
intData[20] = random.Next(0, 100);
var value = random.Next(0, 100);
registers.SetLittleEndian<int>(address: 0, value);
}

// update server buffer content only once per second
// update server register content only once per second
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand All @@ -279,9 +280,10 @@ server.Start();

while (!cts.IsCancellationRequested)
{
var intData = server.GetHoldingRegisterBuffer<int>();
intData[20] = random.Next(0, 100);
var registers = server.GetHoldingRegisters();
var value = random.Next(0, 100);

registers.SetLittleEndian<int>(address: 0, value);
server.Update();

await Task.Delay(TimeSpan.FromMilliseconds(100));
Expand All @@ -292,7 +294,7 @@ Note that in the second example, the ```Task.Delay()``` period is much lower. Si

## Modbus RTU server

When you need a Modbus RTU server, you need to instantiate it like this providing a ```unitIdentifier```, which must be in the range of 1..247 and unique for each Modbus server or slave, respectively:
When you need a Modbus RTU server, you need to instantiate it like this providing a ```unitIdentifier```, which must be in the range of 1..247 and unique for each Modbus server / Modbus slave:

```cs
var server = new ModbusRtuServer(unitIdentifier: 1);
Expand Down Expand Up @@ -327,11 +329,12 @@ registers.SetBigEndian<double>(address: 1, value: 0.85);
```cs
// This will write an 4 byte integer
registers.SetBigEndian<int>(address: 1, value: 99); /* recommended */
registers.SetBigEndian(address: 1, value: 99);

// These will write a 2 byte short
registers.SetBigEndian<short>(address: 1, value: 99); /* recommended */
registers.SetBigEndian(address: 1, value: (short)99);
registers.SetBigEndian<short>(address: 1, value: 99);
```

There are complementary methods for little-endian data and methods for reading data. The full list of `Span<short>` extension methods is:
Expand Down
16 changes: 8 additions & 8 deletions doc/samples/modbus_rtu.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ static void DoServerWork(ModbusRtuServer server)
/* get buffer in standard form (Span<short>) */
var registers = server.GetHoldingRegisters();
registers.SetLittleEndian(startingAddress: 5, random.Next());
registers.SetLittleEndian<int>(startingAddress: 5, random.Next());

// Option B: high performance version, less flexibility
Expand All @@ -153,7 +153,7 @@ static void DoServerWork(ModbusRtuServer server)
When the client is started, the method below is executed only once. After that, the client stops and the user is prompted to enter any key to finish the program.

> [!NOTE]
> All data is returned as ```Span<T>```, which has great advantages but also some limits as described in the repository's README. If you run into these limits, simply call ```ToArray()``` to copy the data into a standard .NET array (e.g. ```var newData = data.ToArray();```)
> All data is returned as ```Span<T>```, which has great advantages but also some limitations as described in the repository's README. If you run into these limitations, simply call ```ToArray()``` to copy the data into a standard .NET array (e.g. ```var newData = data.ToArray();```)
> [!NOTE]
> Remember to always use the correct unit identifier (here: ```0x01```), which was assigned to the server when it was instantiated.
Expand All @@ -164,12 +164,12 @@ static void DoClientWork(ModbusRtuClient client, ILogger logger)
Span<byte> data;

var sleepTime = TimeSpan.FromMilliseconds(100);
var unitIdentifier = (byte)0x01;
var startingAddress = (ushort)0;
var registerAddress = (ushort)0;
var unitIdentifier = 0x01;
var startingAddress = 0;
var registerAddress = 0;

// ReadHoldingRegisters = 0x03, // FC03
data = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadHoldingRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC03 - ReadHoldingRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -189,7 +189,7 @@ static void DoClientWork(ModbusRtuClient client, ILogger logger)
Thread.Sleep(sleepTime);

// ReadInputRegisters = 0x04, // FC04
data = client.ReadInputRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadInputRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC04 - ReadInputRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -199,7 +199,7 @@ static void DoClientWork(ModbusRtuClient client, ILogger logger)
Thread.Sleep(sleepTime);

// WriteSingleRegister = 0x06, // FC06
client.WriteSingleRegister(unitIdentifier, registerAddress, new byte[] { 65, 67 });
client.WriteSingleRegister(unitIdentifier, registerAddress, 127);
logger.LogInformation("FC06 - WriteSingleRegister: Done");
}
```
16 changes: 8 additions & 8 deletions doc/samples/modbus_tcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ static void DoServerWork(ModbusTcpServer server)
/* get buffer in standard form (Span<short>) */
var registers = server.GetHoldingRegisters();
registers.SetLittleEndian(startingAddress: 5, random.Next());
registers.SetLittleEndian<int>(startingAddress: 5, random.Next());

// Option B: high performance version, less flexibility
Expand All @@ -138,20 +138,20 @@ static void DoServerWork(ModbusTcpServer server)
When the client is started, the method below is executed only once. After that, the client stops and the user is prompted to enter any key to finish the program.

> [!NOTE]
> All data is returned as ```Span<T>```, which has great advantages but also some limits as described in the repository's README. If you run into these limits, simply call ```ToArray()``` to copy the data into a standard .NET array (e.g. ```var newData = data.ToArray();```)
> All data is returned as ```Span<T>```, which has great advantages but also some limitations as described in the repository's README. If you run into these limitations, simply call ```ToArray()``` to copy the data into a standard .NET array (e.g. ```var newData = data.ToArray();```)
```cs
static void DoClientWork(ModbusTcpClient client, ILogger logger)
{
Span<byte> data;

var sleepTime = TimeSpan.FromMilliseconds(100);
var unitIdentifier = (byte)0xFF;
var startingAddress = (ushort)0;
var registerAddress = (ushort)0;
var unitIdentifier = 0xFF;
var startingAddress = 0;
var registerAddress = 0;

// ReadHoldingRegisters = 0x03, // FC03
data = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadHoldingRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC03 - ReadHoldingRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -166,7 +166,7 @@ static void DoClientWork(ModbusTcpClient client, ILogger logger)
Thread.Sleep(sleepTime);

// ReadDiscreteInputs = 0x02, // FC02
data = client.ReadDiscreteInputs(unitIdentifier, startingAddress, 10);
data = client.ReadDiscreteInputs<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC02 - ReadDiscreteInputs: Done");
Thread.Sleep(sleepTime);

Expand All @@ -181,7 +181,7 @@ static void DoClientWork(ModbusTcpClient client, ILogger logger)
Thread.Sleep(sleepTime);

// WriteSingleRegister = 0x06, // FC06
client.WriteSingleRegister(unitIdentifier, registerAddress, new byte[] { 65, 67 });
client.WriteSingleRegister(unitIdentifier, registerAddress, 127);
logger.LogInformation("FC06 - WriteSingleRegister: Done");
}
```
16 changes: 8 additions & 8 deletions sample/SampleServerClientRtu/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static async Task Main(string[] args)
DoServerWork(server);
}

// update server buffer content once per second
// update server register content once per second
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand Down Expand Up @@ -101,7 +101,7 @@ static void DoServerWork(ModbusRtuServer server)

/* get buffer in standard form (Span<short>) */
var registers = server.GetHoldingRegisters();
registers.SetLittleEndian(address: 5, random.Next());
registers.SetLittleEndian<int>(address: 5, random.Next());

// Option B: high performance version, less flexibility

Expand All @@ -123,12 +123,12 @@ static void DoClientWork(ModbusRtuClient client, ILogger logger)
Span<byte> data;

var sleepTime = TimeSpan.FromMilliseconds(100);
var unitIdentifier = (byte)0x01;
var startingAddress = (ushort)0;
var registerAddress = (ushort)0;
var unitIdentifier = 0x01;
var startingAddress = 0;
var registerAddress = 0;

// ReadHoldingRegisters = 0x03, // FC03
data = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadHoldingRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC03 - ReadHoldingRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -148,7 +148,7 @@ static void DoClientWork(ModbusRtuClient client, ILogger logger)
Thread.Sleep(sleepTime);

// ReadInputRegisters = 0x04, // FC04
data = client.ReadInputRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadInputRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC04 - ReadInputRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -158,7 +158,7 @@ static void DoClientWork(ModbusRtuClient client, ILogger logger)
Thread.Sleep(sleepTime);

// WriteSingleRegister = 0x06, // FC06
client.WriteSingleRegister(unitIdentifier, registerAddress, new byte[] { 65, 67 });
client.WriteSingleRegister(unitIdentifier, registerAddress, 127);
logger.LogInformation("FC06 - WriteSingleRegister: Done");
}
}
Expand Down
16 changes: 8 additions & 8 deletions sample/SampleServerClientTcp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static async Task Main(string[] args)
DoServerWork(server);
}

// update server buffer content once per second
// update server register content once per second
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand Down Expand Up @@ -85,7 +85,7 @@ static void DoServerWork(ModbusTcpServer server)

/* get buffer in standard form (Span<short>) */
var registers = server.GetHoldingRegisters();
registers.SetLittleEndian(address: 5, random.Next());
registers.SetLittleEndian<int>(address: 5, random.Next());

// Option B: high performance version, less flexibility

Expand All @@ -107,12 +107,12 @@ static void DoClientWork(ModbusTcpClient client, ILogger logger)
Span<byte> data;

var sleepTime = TimeSpan.FromMilliseconds(100);
var unitIdentifier = (byte)0xFF;
var startingAddress = (ushort)0;
var registerAddress = (ushort)0;
var unitIdentifier = 0xFF;
var startingAddress = 0;
var registerAddress = 0;

// ReadHoldingRegisters = 0x03, // FC03
data = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadHoldingRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC03 - ReadHoldingRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -132,7 +132,7 @@ static void DoClientWork(ModbusTcpClient client, ILogger logger)
Thread.Sleep(sleepTime);

// ReadInputRegisters = 0x04, // FC04
data = client.ReadInputRegisters(unitIdentifier, startingAddress, 10);
data = client.ReadInputRegisters<byte>(unitIdentifier, startingAddress, 10);
logger.LogInformation("FC04 - ReadInputRegisters: Done");
Thread.Sleep(sleepTime);

Expand All @@ -142,7 +142,7 @@ static void DoClientWork(ModbusTcpClient client, ILogger logger)
Thread.Sleep(sleepTime);

// WriteSingleRegister = 0x06, // FC06
client.WriteSingleRegister(unitIdentifier, registerAddress, new byte[] { 65, 67 });
client.WriteSingleRegister(unitIdentifier, registerAddress, 127);
logger.LogInformation("FC06 - WriteSingleRegister: Done");
}
}
Expand Down
Loading

0 comments on commit a9478dd

Please sign in to comment.