Skip to content

Commit

Permalink
fixes #33 - ReadRegistersBuilder address splitter calculates start ad…
Browse files Browse the repository at this point in the history
…dress incorrectly when value is 0.

also fixes case when addresses overlap then quantity was calculated incorrectly
  • Loading branch information
aldas committed Jul 11, 2019
1 parent e22a138 commit 4157cab
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 4 deletions.
13 changes: 11 additions & 2 deletions src/Composer/AddressSplitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,23 @@ public function split(array $addresses): array
$quantity = null;
$chunk = [];
$previousAddress = null;
$maxAvailableRegister = null;
foreach ($addrs as $currentAddress) {
/** @var Address $currentAddress */
$currentStartAddress = $currentAddress->getAddress();
if (!$startAddress) {
if ($startAddress === null) {
$startAddress = $currentStartAddress;
}

$nextAvailableRegister = $currentStartAddress + $currentAddress->getSize();

// in case next address is smaller than previous address with its size we need to make sure that quantity does not change
// as those addresses overlap
if ($maxAvailableRegister === null || $nextAvailableRegister > $maxAvailableRegister) {
$maxAvailableRegister = $nextAvailableRegister;
} else if ($nextAvailableRegister < $maxAvailableRegister) {
$nextAvailableRegister = $maxAvailableRegister;
}
$previousQuantity = $quantity;
$quantity = $nextAvailableRegister - $startAddress;
if ($this->shouldSplit($currentAddress, $quantity, $previousAddress, $previousQuantity)) {
Expand All @@ -76,4 +85,4 @@ protected function shouldSplit(Address $currentAddress, int $currentQuantity, Ad
return $currentQuantity >= $this->getMaxAddressesPerModbusRequest();
}

}
}
141 changes: 139 additions & 2 deletions tests/unit/Composer/Read/ReadRegistersBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use ModbusTcpClient\Composer\Address;
use ModbusTcpClient\Composer\Read\BitReadAddress;
use ModbusTcpClient\Composer\Read\ByteReadAddress;
use ModbusTcpClient\Composer\Read\ReadAddress;
use ModbusTcpClient\Composer\Read\ReadRegistersBuilder;
use ModbusTcpClient\Composer\Read\StringReadAddress;
use ModbusTcpClient\Packet\ModbusFunction\ReadHoldingRegistersRequest;
Expand Down Expand Up @@ -306,16 +307,152 @@ public function typesProvider(): array
];
}

public function testIsNotEmptyTrue() {
public function testIsNotEmptyTrue()
{
$builder = ReadRegistersBuilder::newReadHoldingRegisters('tcp://127.0.0.1:5022')
->bit(278, 5, 'dirchange1_status');

$this->assertTrue($builder->isNotEmpty());
}

public function testIsNotEmptyFalse() {
public function testIsNotEmptyFalse()
{
$builder = ReadRegistersBuilder::newReadHoldingRegisters('tcp://127.0.0.1:5022');

$this->assertFalse($builder->isNotEmpty());
}

public function test0Address()
{
$requests = ReadRegistersBuilder::newReadHoldingRegisters('tcp://127.0.0.1:5022')
->int64(0, 'realtime')
->int32(4, 'sys time')
->build();

$this->assertCount(1, $requests);

$request = $requests[0]->getRequest();

$this->assertEquals(0, $request->getStartAddress());
$this->assertEquals(6, $request->getQuantity());

$addresses = $requests[0]->getAddresses();
$this->assertCount(2, $addresses);

/** @var ReadAddress $address */
$address = $addresses[0];
$this->assertEquals(Address::TYPE_INT64, $address->getType());
$this->assertEquals(0, $address->getAddress());
$this->assertEquals('realtime', $address->getName());
$this->assertEquals(4, $address->getSize());

/** @var ReadAddress $address */
$address = $addresses[1];
$this->assertEquals(Address::TYPE_INT32, $address->getType());
$this->assertEquals(4, $address->getAddress());
$this->assertEquals('sys time', $address->getName());
$this->assertEquals(2, $address->getSize());
}

public function requestValuesProvider(): array
{
return [
'first address is bigger in size than second' => [
[
0 => [
'addresses' => [
['int64', 1, 'addr1'],
['int32', 2, 'addr2'],
],
'startAddress' => 1,
'quantity' => 4,
]
],
],
'addresses overlap due their size' => [
[
0 => [
'addresses' => [
['int64', 0, 'addr1'],
['int64', 2, 'addr2'],
],
'startAddress' => 0,
'quantity' => 6,
]
],
],
'first val is at 0 address' => [
[
0 => [
'addresses' => [
['int64', 0, 'addr1'],
['int32', 4, 'addr2'],
],
'startAddress' => 0,
'quantity' => 6,
]
],
],
'first val is at 1 address' => [
[
0 => [
'addresses' => [
['int64', 1, 'addr1'],
['int32', 5, 'addr2'],
],
'startAddress' => 1,
'quantity' => 6,
]
],
],
'first val is at 0 address vol2' => [
[
0 => [
'addresses' => [
['int64', 0, 'realtime'],
['int32', 4, 'sys time'],
['int16', 6, 'day'],
['int16', 7, 'month'],
],
'startAddress' => 0,
'quantity' => 8,
]
],
],
];
}

/**
* @dataProvider requestValuesProvider
*/
public function testRequestValues($requestArgs)
{
$builder = ReadRegistersBuilder::newReadHoldingRegisters('tcp://127.0.0.1:5022');

foreach ($requestArgs as $args) {
if (empty($args['addresses'])) {
continue;
}
foreach ($args['addresses'] as list($method, $address, $name)) {
$builder = $builder->$method($address, $name);
}
}

$requests = $builder->build();

$this->assertCount(count($requestArgs), $requests);

$i = 0;
foreach ($requestArgs as $args) {
$request = $requests[$i]->getRequest();


$this->assertEquals($args['startAddress'], $request->getStartAddress());
$this->assertEquals($args['quantity'], $request->getQuantity());

$this->assertCount(count($args['addresses']), $requests[$i]->getAddresses());

$i++;
}
}
}

0 comments on commit 4157cab

Please sign in to comment.