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.
-
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