Replies: 6 comments 6 replies
-
Ideally you would use for writing "22 (0x16) Mask Write Register" (https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf page 36) but I have not implemented it here at the moment. so you need to combine |
Beta Was this translation helpful? Give feedback.
-
If it is only single register you could use FC6 to write it https://github.com/aldas/modbus-tcp-client/blob/master/examples/fc6.php and use bitwise operators to set n-th bit. $readValue = 0;
$bitPosition = 2;
$writeValue = $readValue | (1 << $bitPosition); // this set that bit to 1. clearing is different
$startAddress = 12288;
$unitID = 0;
$packet = new WriteSingleRegisterRequest($startAddress, $writeValue, $unitID); to check if bit is set use modbus-tcp-client/src/Utils/Types.php Line 243 in 20b5a65 |
Beta Was this translation helpful? Give feedback.
-
@mcazzador I have added FC22 Mask Write Register support in v3.0.0. Please see this example https://github.com/aldas/modbus-tcp-client/blob/master/examples/fc22.php https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf page 36 has more detailed explanation of that function |
Beta Was this translation helpful? Give feedback.
-
Thank, i need to use php 7.0.33 i can't upgrade
maybe i can use the secondo trick you suggest.
Thanks
Il 11/04/2022 21:10, Martti T. ha scritto:
…
Can you add another apt-repository to get newer php version?
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php8.1
or you could take
https://github.com/aldas/modbus-tcp-client/blob/master/src/Packet/ModbusFunction/MaskWriteRegisterRequest.php
<https://urlsand.esvalabs.com/?u=https%3A%2F%2Fgithub.com%2Faldas%2Fmodbus-tcp-client%2Fblob%2Fmaster%2Fsrc%2FPacket%2FModbusFunction%2FMaskWriteRegisterRequest.php&e=8e0f821d&h=f185b855&f=y&p=y>
code and add it to your code and remove feature that your php version
does not support (probably property types and some return types)
—
Reply to this email directly, view it on GitHub
<https://urlsand.esvalabs.com/?u=https%3A%2F%2Fgithub.com%2Faldas%2Fmodbus-tcp-client%2Fdiscussions%2F107%23discussioncomment-2547122&e=8e0f821d&h=dbe0eef2&f=y&p=y>,
or unsubscribe
<https://urlsand.esvalabs.com/?u=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAPMZE74KNWK64MF6RGUR6ELVER2MHANCNFSM5SZFZECQ&e=8e0f821d&h=1a3e295e&f=y&p=y>.
You are receiving this because you were mentioned.Web Bug from
https://github.com/notifications/beacon/APMZE7YGHOB2BPEUEJFPINDVER2MHA5CNFSM5SZFZEC2YY3PNVWWK3TUL52HS4DFWFCGS43DOVZXG2LPNZBW63LNMVXHJKTDN5WW2ZLOORPWSZGOAATN3MQ.gifMessage
ID:
***@***.***>
--
Messaggio analizzato da Libraesva ESG.
Segnala come spam.
<http://mailgateway-3.netlite.it/action/3D4FF639E2.AB360/learn-spam>
Mettilo in blacklist.
<http://mailgateway-3.netlite.it/action/3D4FF639E2.AB360/blacklist>
--
Rispetta l'ambiente: se non ti è necessario, non stampare questa mail.
Le informazioni contenute in questa e-mail e nei files eventualmente
allegati sono destinate unicamente ai destinatari della stessa
e sono da considerarsi strettamente riservate.
E' proibito copiare, salvare, utilizzare, inoltrare a terzi e diffondere
il contenuto della presente senza il preventivo consenso, ai sensi
dell'articolo 616 c.p. e della Legge n. 196/2003.
Se avete ricevuto questo messaggio per errore siete pregati di comunicarlo
immediatamente all'indirizzo mittente, nonché di cancellarne il contenuto
senza procedere ad ulteriore o differente trattamento.
******************************************
Ing. Matteo Cazzador
NetLite snc di Cazzador Gagliardi
Corso Vittorio Emanuele II, 188 37069
Villafranca di Verona VR
Tel 0454856656
Fax 0454856655
***@***.***
Web:http://www.netlite.it
******************************************
|
Beta Was this translation helpful? Give feedback.
-
thank's perfect i follow your suggest!
Ottieni BlueMail per Android
Il giorno 11 Apr 2022, 21:20, alle ore 21:20, "Martti T." ***@***.***> ha scritto:
maybe this would work:
```php
<?php
use ModbusTcpClient\Network\BinaryStreamConnection;
use ModbusTcpClient\Packet\ErrorResponse;
use ModbusTcpClient\Packet\ModbusRequest;
use ModbusTcpClient\Packet\ProtocolDataUnitRequest;
use ModbusTcpClient\Packet\StartAddressResponse;
use ModbusTcpClient\Packet\Word;
use ModbusTcpClient\Utils\Types;
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/logger.php';
class MaskWriteRegisterRequest extends ProtocolDataUnitRequest
implements ModbusRequest
{
/**
* @var int AND mask to be sent to modbus
*/
private $andMask;
/**
* @var int OR mask to be sent to modbus
*/
private $orMask;
public function __construct(int $startAddress, int $andMask, int
$orMask, int $unitId = 0, int $transactionId = null)
{
parent::__construct($startAddress, $unitId, $transactionId);
$this->andMask = $andMask;
$this->orMask = $orMask;
$this->validate();
}
public function validate()
{
parent::validate();
// value is 2 bytes in packet so it in range of uint16 (0 - 65535) or
int16 (-32768 - +32767)
if (!(($this->andMask >= Types::MIN_VALUE_INT16) && ($this->andMask <=
Types::MAX_VALUE_UINT16))) {
throw new InvalidArgumentException("AND mask is out of range (u)int16:
{$this->andMask}", 3);
}
if (!(($this->orMask >= Types::MIN_VALUE_INT16) && ($this->orMask <=
Types::MAX_VALUE_UINT16))) {
throw new InvalidArgumentException("OR mask is out of range (u)int16:
{$this->orMask}", 3);
}
}
public function getFunctionCode()
{
return 22;
}
public function __toString()
{
return parent::__toString()
. Types::toRegister($this->getANDMask())
. Types::toRegister($this->getORMask());
}
/**
* @return int
*/
public function getANDMask()
{
return $this->andMask;
}
/**
* @return int
*/
public function getORMask()
{
return $this->orMask;
}
/**
* @return Word
*/
public function getANDMaskAsWord()
{
return new Word(Types::toInt16($this->andMask));
}
/**
* @return Word
*/
public function getORMaskAsWord()
{
return new Word(Types::toInt16($this->orMask));
}
protected function getLengthInternal(): int
{
return parent::getLengthInternal() + 4; // AND mask size (2 bytes) + OR
mask size (2 bytes)
}
/**
* Parses binary string to MaskWriteRegisterRequest or return
ErrorResponse on failure
*
* @param string $binaryString
* @return MaskWriteRegisterRequest|ErrorResponse
*/
public static function parse(string $binaryString)
{
return self::parseStartAddressPacket(
$binaryString,
14,
22,
function (int $transactionId, int $unitId, int $startAddress) use
($binaryString) {
$andMask = Types::parseInt16($binaryString[10] . $binaryString[11]);
$orMask = Types::parseInt16($binaryString[12] . $binaryString[13]);
return new self($startAddress, $andMask, $orMask, $unitId,
$transactionId);
}
);
}
}
class MaskWriteRegisterResponse extends StartAddressResponse
{
/**
* @var int AND mask to be sent to modbus
*/
private $andMask;
/**
* @var int OR mask to be sent to modbus
*/
private $orMask;
public function __construct(string $rawData, int $unitId = 0, int
$transactionId = null)
{
parent::__construct($rawData, $unitId, $transactionId);
$this->andMask = Types::parseUInt16(substr($rawData, 2, 2));
$this->orMask = Types::parseUInt16(substr($rawData, 4, 2));
}
public function getFunctionCode()
{
return 22;
}
protected function getLengthInternal()
{
return parent::getLengthInternal() + 4; //register is 4 bytes
}
public function __toString()
{
return parent::__toString()
. Types::toRegister($this->getANDMask())
. Types::toRegister($this->getORMask());
}
/**
* @return int
*/
public function getANDMask()
{
return $this->andMask;
}
/**
* @return int
*/
public function getORMask()
{
return $this->orMask;
}
/**
* @return Word
*/
public function getANDMaskAsWord()
{
return new Word(Types::toInt16($this->andMask));
}
/**
* @return Word
*/
public function getORMaskAsWord()
{
return new Word(Types::toInt16($this->orMask));
}
}
$connection = BinaryStreamConnection::getBuilder()
->setPort(5020)
->setHost('127.0.0.1')
->setLogger(new EchoLogger())
->build();
$readStartAddress = 12288;
$bitPosition = 2; // third bit (starts from 0)
$ANDMask = 0x0000; // 2 bytes
$ANDMask |= (1 << $bitPosition); // set the bit, set third bit to 1.
$ANDMask = 0x0004, 0b00000100
$ORMask = 0x0007; // 2 bytes, bin = 0b00000111
$ORMask &= ~(1 << $bitPosition); // clear the bit, set third bit to 0.
$ORMask = 0x0003, 0b00000011
$unitID = 0;
$packet = new MaskWriteRegisterRequest(
$readStartAddress,
$ANDMask,
$ORMask,
$unitID
); // NB: This is Modbus TCP packet not Modbus RTU over TCP!
echo 'Packet to be sent (in hex): ' . $packet->toHex() . PHP_EOL;
try {
$binaryData = $connection->connect()->sendAndReceive($packet);
echo 'Binary received (in hex): ' . unpack('H*', $binaryData)[1] .
PHP_EOL;
if (ErrorResponse::is($binaryData)) {
throw new Exception("response is modbus error");
}
} catch (Exception $exception) {
echo 'An exception occurred' . PHP_EOL;
echo $exception->getMessage() . PHP_EOL;
echo $exception->getTraceAsString() . PHP_EOL;
} finally {
$connection->close();
}
```
--
Reply to this email directly or view it on GitHub:
https://urlsand.esvalabs.com/?u=https%3A%2F%2Fgithub.com%2Faldas%2Fmodbus-tcp-client%2Fdiscussions%2F107%23discussioncomment-2547180&e=8e0f821d&h=f8323725&f=y&p=y
You are receiving this because you were mentioned.
Message ID:
***@***.***>
…--
Messaggio analizzato da Libraesva ESG.
Seguire il link qui sotto per segnalarlo come spam:
http://mailgateway-3.netlite.it/action/E2E77639E8.AB5F4/learn-spam
Seguire il link qui sotto per mettere in blacklist il mittente:
http://mailgateway-3.netlite.it/action/E2E77639E8.AB5F4/blacklist
|
Beta Was this translation helpful? Give feedback.
-
Thanks! today i test it.
Il 11/04/2022 21:20, Martti T. ha scritto:
…
maybe this would work:
<?php
use ModbusTcpClient\Network\BinaryStreamConnection;
use ModbusTcpClient\Packet\ErrorResponse;
use ModbusTcpClient\Packet\ModbusRequest;
use ModbusTcpClient\Packet\ProtocolDataUnitRequest;
use ModbusTcpClient\Packet\StartAddressResponse;
use ModbusTcpClient\Packet\Word;
use ModbusTcpClient\Utils\Types;
require __DIR__ .'/../vendor/autoload.php';
require __DIR__ .'/logger.php';
class MaskWriteRegisterRequest extends ProtocolDataUnitRequest implements ModbusRequest
{
/**
* @var int AND mask to be sent to modbus
*/
private $andMask;
/**
* @var int OR mask to be sent to modbus
*/
private $orMask;
public function __construct(int $startAddress,int $andMask,int $orMask,int $unitId =0,int $transactionId =null)
{
parent::__construct($startAddress,$unitId,$transactionId);
$this->andMask =$andMask;
$this->orMask =$orMask;
$this->validate();
}
public function validate()
{
parent::validate();
// value is 2 bytes in packet so it in range of uint16 (0 - 65535) or
int16 (-32768 - +32767)
if (!(($this->andMask >=Types::MIN_VALUE_INT16) && ($this->andMask <=Types::MAX_VALUE_UINT16))) {
throw new InvalidArgumentException("AND mask is out of range (u)int16: {$this->andMask}",3);
}
if (!(($this->orMask >=Types::MIN_VALUE_INT16) && ($this->orMask <=Types::MAX_VALUE_UINT16))) {
throw new InvalidArgumentException("OR mask is out of range (u)int16: {$this->orMask}",3);
}
}
public function getFunctionCode()
{
return 22;
}
public function __toString()
{
return parent::__toString()
.Types::toRegister($this->getANDMask())
.Types::toRegister($this->getORMask());
}
/**
* @return int
*/
public function getANDMask()
{
return $this->andMask;
}
/**
* @return int
*/
public function getORMask()
{
return $this->orMask;
}
/**
* @return Word
*/
public function getANDMaskAsWord()
{
return new Word(Types::toInt16($this->andMask));
}
/**
* @return Word
*/
public function getORMaskAsWord()
{
return new Word(Types::toInt16($this->orMask));
}
protected function getLengthInternal():int
{
return parent::getLengthInternal() +4;// AND mask size (2 bytes) + OR mask size (2 bytes)
}
/**
* Parses binary string to MaskWriteRegisterRequest or return
ErrorResponse on failure
*
* @param string $binaryString
* @return MaskWriteRegisterRequest|ErrorResponse
*/
public static function parse(string $binaryString)
{
return self::parseStartAddressPacket(
$binaryString,
14,
22,
function (int $transactionId,int $unitId,int $startAddress)use ($binaryString) {
$andMask =Types::parseInt16($binaryString[10] .$binaryString[11]);
$orMask =Types::parseInt16($binaryString[12] .$binaryString[13]);
return new self($startAddress,$andMask,$orMask,$unitId,$transactionId);
}
);
}
}
class MaskWriteRegisterResponse extends StartAddressResponse
{
/**
* @var int AND mask to be sent to modbus
*/
private $andMask;
/**
* @var int OR mask to be sent to modbus
*/
private $orMask;
public function __construct(string $rawData,int $unitId =0,int $transactionId =null)
{
parent::__construct($rawData,$unitId,$transactionId);
$this->andMask =Types::parseUInt16(substr($rawData,2,2));
$this->orMask =Types::parseUInt16(substr($rawData,4,2));
}
public function getFunctionCode()
{
return 22;
}
protected function getLengthInternal()
{
return parent::getLengthInternal() +4;//register is 4 bytes
}
public function __toString()
{
return parent::__toString()
.Types::toRegister($this->getANDMask())
.Types::toRegister($this->getORMask());
}
/**
* @return int
*/
public function getANDMask()
{
return $this->andMask;
}
/**
* @return int
*/
public function getORMask()
{
return $this->orMask;
}
/**
* @return Word
*/
public function getANDMaskAsWord()
{
return new Word(Types::toInt16($this->andMask));
}
/**
* @return Word
*/
public function getORMaskAsWord()
{
return new Word(Types::toInt16($this->orMask));
}
}
$connection =BinaryStreamConnection::getBuilder()
->setPort(5020)
->setHost('127.0.0.1')
->setLogger(new EchoLogger())
->build();
$readStartAddress =12288;
$bitPosition =2;// third bit (starts from 0)
$ANDMask =0x0000;// 2 bytes
$ANDMask |= (1 <<$bitPosition);// set the bit, set third bit to 1. $ANDMask = 0x0004, 0b00000100
$ORMask =0x0007;// 2 bytes, bin = 0b00000111
$ORMask &= ~(1 <<$bitPosition);// clear the bit, set third bit to 0. $ORMask = 0x0003, 0b00000011
$unitID =0;
$packet =new MaskWriteRegisterRequest(
$readStartAddress,
$ANDMask,
$ORMask,
$unitID
);// NB: This is Modbus TCP packet not Modbus RTU over TCP!
echo 'Packet to be sent (in hex): ' .$packet->toHex() .PHP_EOL;
try {
$binaryData =$connection->connect()->sendAndReceive($packet);
echo 'Binary received (in hex): ' .unpack('H*',$binaryData)[1] .PHP_EOL;
if (ErrorResponse::is($binaryData)) {
throw new Exception("response is modbus error");
}
}catch (Exception $exception) {
echo 'An exception occurred' .PHP_EOL;
echo $exception->getMessage() .PHP_EOL;
echo $exception->getTraceAsString() .PHP_EOL;
}finally {
$connection->close();
}
—
Reply to this email directly, view it on GitHub
<https://urlsand.esvalabs.com/?u=https%3A%2F%2Fgithub.com%2Faldas%2Fmodbus-tcp-client%2Fdiscussions%2F107%23discussioncomment-2547180&e=8e0f821d&h=f8323725&f=y&p=y>,
or unsubscribe
<https://urlsand.esvalabs.com/?u=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAPMZE76I64IKGP3EPKX5UFLVER3QHANCNFSM5SZFZECQ&e=8e0f821d&h=6fd5ff0b&f=y&p=y>.
You are receiving this because you were mentioned.Web Bug from
https://github.com/notifications/beacon/APMZE72G67ZRQEPGRRWQDWTVER3QHA5CNFSM5SZFZEC2YY3PNVWWK3TUL52HS4DFWFCGS43DOVZXG2LPNZBW63LNMVXHJKTDN5WW2ZLOORPWSZGOAATN33A.gifMessage
ID:
***@***.***>
--
Messaggio analizzato da Libraesva ESG.
Segnala come spam.
<http://mailgateway-3.netlite.it/action/E2E77639E8.AB5F4/learn-spam>
Mettilo in blacklist.
<http://mailgateway-3.netlite.it/action/E2E77639E8.AB5F4/blacklist>
--
Rispetta l'ambiente: se non ti è necessario, non stampare questa mail.
Le informazioni contenute in questa e-mail e nei files eventualmente
allegati sono destinate unicamente ai destinatari della stessa
e sono da considerarsi strettamente riservate.
E' proibito copiare, salvare, utilizzare, inoltrare a terzi e diffondere
il contenuto della presente senza il preventivo consenso, ai sensi
dell'articolo 616 c.p. e della Legge n. 196/2003.
Se avete ricevuto questo messaggio per errore siete pregati di comunicarlo
immediatamente all'indirizzo mittente, nonché di cancellarne il contenuto
senza procedere ad ulteriore o differente trattamento.
******************************************
Ing. Matteo Cazzador
NetLite snc di Cazzador Gagliardi
Corso Vittorio Emanuele II, 188 37069
Villafranca di Verona VR
Tel 0454856656
Fax 0454856655
***@***.***
Web:http://www.netlite.it
******************************************
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi, i nedd to read a UINT16 (tcp/ip) registry modbus F3 and set to 0 only bit with value 1 and then write the new value to the sam especified registry (F16).
read -> ...0101
write -> ....0000
Which is the best method to do so?
Thanks
Beta Was this translation helpful? Give feedback.
All reactions