PHP Classes

File: tests/Unit/Protocol/HistoryReadServiceTest.php

Recommend this page to a friend!
  Packages of Gianfrancesco Aurecchia   OPC UA Client   tests/Unit/Protocol/HistoryReadServiceTest.php   Download  
File: tests/Unit/Protocol/HistoryReadServiceTest.php
Role: Example script
Content type: text/plain
Description: Example script
Class: OPC UA Client
Control devices that support the OPC UA protocol
Author: By
Last change:
Date: 5 days ago
Size: 6,968 bytes
 

Contents

Class file image Download
<?php

declare(strict_types=1);

use
PhpOpcua\Client\Encoding\BinaryDecoder;
use
PhpOpcua\Client\Encoding\BinaryEncoder;
use
PhpOpcua\Client\Module\History\HistoryReadService;
use
PhpOpcua\Client\Protocol\MessageHeader;
use
PhpOpcua\Client\Protocol\SessionService;
use
PhpOpcua\Client\Types\BuiltinType;
use
PhpOpcua\Client\Types\NodeId;

function
writeHistoryResponseHeader(BinaryEncoder $encoder, int $statusCode = 0): void
{
   
$encoder->writeInt64(0);
   
$encoder->writeUInt32(1);
   
$encoder->writeUInt32($statusCode);
   
$encoder->writeByte(0);
   
$encoder->writeInt32(0);
   
$encoder->writeNodeId(NodeId::numeric(0, 0));
   
$encoder->writeByte(0);
}

function
writeHistoryMessagePrefix(BinaryEncoder $encoder): void
{
   
$encoder->writeUInt32(1);
   
$encoder->writeUInt32(1);
   
$encoder->writeUInt32(1);
}

describe('HistoryReadService encoding', function () {

   
it('encodes a HistoryReadRaw request', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$bytes = $service->encodeHistoryReadRawRequest(
           
1,
           
NodeId::numeric(0, 0),
           
NodeId::numeric(1, 100),
            new
DateTimeImmutable('2024-01-01'),
            new
DateTimeImmutable('2024-01-02'),
           
100,
           
true,
        );

       
$decoder = new BinaryDecoder($bytes);
       
$header = MessageHeader::decode($decoder);
       
expect($header->getMessageType())->toBe('MSG');
       
expect(strlen($bytes))->toBeGreaterThan(50);
    });

   
it('encodes a HistoryReadProcessed request', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$bytes = $service->encodeHistoryReadProcessedRequest(
           
1,
           
NodeId::numeric(0, 0),
           
NodeId::numeric(1, 100),
            new
DateTimeImmutable('2024-01-01'),
            new
DateTimeImmutable('2024-01-02'),
           
500.0,
           
NodeId::numeric(0, 2341),
        );

       
$decoder = new BinaryDecoder($bytes);
       
$header = MessageHeader::decode($decoder);
       
expect($header->getMessageType())->toBe('MSG');
    });

   
it('encodes a HistoryReadAtTime request', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$bytes = $service->encodeHistoryReadAtTimeRequest(
           
1,
           
NodeId::numeric(0, 0),
           
NodeId::numeric(1, 100),
            [new
DateTimeImmutable('2024-01-01 12:00:00'), new DateTimeImmutable('2024-01-01 13:00:00')],
        );

       
$decoder = new BinaryDecoder($bytes);
       
$header = MessageHeader::decode($decoder);
       
expect($header->getMessageType())->toBe('MSG');
    });
});

describe('HistoryReadService decoding', function () {

   
it('decodes a HistoryReadResponse with HistoryData values', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$encoder = new BinaryEncoder();
       
writeHistoryMessagePrefix($encoder);
       
$encoder->writeNodeId(NodeId::numeric(0, 667)); // HistoryReadResponse
       
writeHistoryResponseHeader($encoder);

       
// Results: 1 HistoryReadResult
       
$encoder->writeInt32(1);
       
$encoder->writeUInt32(0); // StatusCode
       
$encoder->writeByteString(null); // ContinuationPoint

        // HistoryData ExtensionObject (TypeId 658)
       
$encoder->writeNodeId(NodeId::numeric(0, 658));
       
$encoder->writeByte(0x01); // Has body

        // Build the body separately to know its length
       
$bodyEncoder = new BinaryEncoder();
       
// DataValues array: 2 values
       
$bodyEncoder->writeInt32(2);
       
// DataValue 1: value only
       
$bodyEncoder->writeByte(0x01);
       
$bodyEncoder->writeByte(BuiltinType::Double->value);
       
$bodyEncoder->writeDouble(23.5);
       
// DataValue 2: value only
       
$bodyEncoder->writeByte(0x01);
       
$bodyEncoder->writeByte(BuiltinType::Double->value);
       
$bodyEncoder->writeDouble(24.1);

       
$body = $bodyEncoder->getBuffer();
       
$encoder->writeInt32(strlen($body));
       
$encoder->writeRawBytes($body);

       
// DiagnosticInfos: empty
       
$encoder->writeInt32(0);

       
$decoder = new BinaryDecoder($encoder->getBuffer());
       
$result = $service->decodeHistoryReadResponse($decoder);
       
expect($result)->toHaveCount(2);
       
expect($result[0]->getValue())->toBe(23.5);
       
expect($result[1]->getValue())->toBe(24.1);
    });

   
it('decodes a HistoryReadResponse with unknown history type (skips body)', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$encoder = new BinaryEncoder();
       
writeHistoryMessagePrefix($encoder);
       
$encoder->writeNodeId(NodeId::numeric(0, 667));
       
writeHistoryResponseHeader($encoder);

       
$encoder->writeInt32(1);
       
$encoder->writeUInt32(0);
       
$encoder->writeByteString(null);

       
// Unknown history type (TypeId 9999)
       
$encoder->writeNodeId(NodeId::numeric(0, 9999));
       
$encoder->writeByte(0x01);
       
$fakeBody = str_repeat("\x00", 20);
       
$encoder->writeInt32(strlen($fakeBody));
       
$encoder->writeRawBytes($fakeBody);

       
$encoder->writeInt32(0);

       
$decoder = new BinaryDecoder($encoder->getBuffer());
       
$result = $service->decodeHistoryReadResponse($decoder);
       
expect($result)->toBe([]);
    });

   
it('decodes a HistoryReadResponse with no body encoding', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$encoder = new BinaryEncoder();
       
writeHistoryMessagePrefix($encoder);
       
$encoder->writeNodeId(NodeId::numeric(0, 667));
       
writeHistoryResponseHeader($encoder);

       
// 1 result with no-body extension object
       
$encoder->writeInt32(1);
       
$encoder->writeUInt32(0);
       
$encoder->writeByteString(null);
       
$encoder->writeNodeId(NodeId::numeric(0, 0));
       
$encoder->writeByte(0x00); // No body

       
$encoder->writeInt32(0);

       
$decoder = new BinaryDecoder($encoder->getBuffer());
       
$result = $service->decodeHistoryReadResponse($decoder);
       
expect($result)->toBe([]);
    });

   
it('decodes an empty HistoryReadResponse', function () {
       
$session = new SessionService(1, 1);
       
$service = new HistoryReadService($session);

       
$encoder = new BinaryEncoder();
       
writeHistoryMessagePrefix($encoder);
       
$encoder->writeNodeId(NodeId::numeric(0, 667));
       
writeHistoryResponseHeader($encoder);
       
$encoder->writeInt32(0); // 0 results
       
$encoder->writeInt32(0); // 0 diagnostics

       
$decoder = new BinaryDecoder($encoder->getBuffer());
       
$result = $service->decodeHistoryReadResponse($decoder);
       
expect($result)->toBe([]);
    });
});