OPC UA পরিচিতি ── PLC ও যন্ত্রের ডেটা Windows অ্যাপে সংগ্রহ করা

· · Windows, OPC UA, উৎপাদন শিল্প, PLC, C#, .NET, যোগাযোগ, সার্টিফিকেট

X-এ পোস্ট করুন
সংশোধন ইতিহাস (প্রথম সংস্করণ, 1 Nov 2026 তারিখে প্রকাশিত)
প্রথম প্রকাশ
এই নিবন্ধটি উদ্ধৃত করুন(DOI: 10.5281/zenodo.23968411)

এই নিবন্ধটি Zenodo-তে আর্কাইভ করা আছে। নিচে সেই DOI রয়েছে যা সবসময় সর্বশেষ সংস্করণে নিয়ে যায়, এবং সেই DOI-ও যা আপনি পড়ছেন এমন সংস্করণে আবদ্ধ।

Go Komura (2026). OPC UA পরিচিতি ── PLC ও যন্ত্রের ডেটা Windows অ্যাপে সংগ্রহ করা. KomuraSoft LLC. https://doi.org/10.5281/zenodo.23968411 https://comcomponent.com/bn/blog/opc-ua-windows-data-collection/

DOI (সর্বশেষ সংস্করণ)
10.5281/zenodo.23968411
DOI (এই সংস্করণ)
10.5281/zenodo.23968412

PLC বা যন্ত্রের ডেটা Windows অ্যাপে সংগ্রহ করার সময়, যন্ত্রে OPC UA সার্ভার থাকলে প্রতিটি নির্মাতার জন্য আলাদা যোগাযোগ লিখতে না-ও হতে পারে। তবে শুধু সংযোগ করে মান পড়াই যথেষ্ট নয়। মানের সঙ্গে ফেরা স্ট্যাটাস আর টাইমস্ট্যাম্প, পরিবর্তন জানিয়ে দেওয়ার subscription, সার্টিফিকেট দিয়ে সংযোগের অনুমতি, আর বিচ্ছিন্ন হওয়ার পর ফিরে আসার উপায় না জানলে, সংগ্রহ করা ডেটার ওপর পরে ভরসা করা যায় না।

এই নিবন্ধে OPC UA-এর যে অংশগুলো ডেটা সংগ্রহে লাগে, সেগুলো C# ক্লায়েন্ট আসলে চালিয়ে পাওয়া ফলাফলসহ ব্যাখ্যা করা হয়েছে। ক্লায়েন্টের জন্য OPC Foundation-এর .NET লাইব্রেরি ব্যবহার করেছি, আর অপর প্রান্তে একটি সিমুলেটেড যন্ত্রের সার্ভার রেখেছি। নির্দিষ্ট কোনো PLC বা যন্ত্রে এটি পরীক্ষা করিনি। প্রতিটি যন্ত্রের সেটিং সেই যন্ত্রের ডকুমেন্টেশনে মিলিয়ে দেখুন।

GigE Vision ও USB3 Vision ক্যামেরা থেকে ছবি সংগ্রহের কথা “Dropped Frames with GigE Vision and USB3 Vision Cameras“-এ, আর সিরিয়াল যোগাযোগের যন্ত্রের কথা “Serial Communication App Pitfalls“-এ লেখা আছে।

OPC UA আর OPC Classic-এর পার্থক্য

OPC Classic-এর স্পেসিফিকেশনগুলো সফটওয়্যার উপাদানের মধ্যে ডেটা আদান-প্রদানে Windows-এর COM/DCOM ব্যবহার করে। প্রক্রিয়ার ডেটার জন্য OPC DA, অ্যালার্মের জন্য OPC A&E আর ইতিহাসের জন্য OPC HDA আলাদা আলাদা স্পেসিফিকেশন হিসেবে নির্ধারিত1।

OPC Foundation 2008 সালে OPC UA (Unified Architecture) প্রকাশ করে। OPC UA নির্দিষ্ট কোনো প্ল্যাটফর্মের ওপর নির্ভর না করা একটি service-oriented architecture, যা Classic-এর প্রতিটি স্পেসিফিকেশনের কাজ একসঙ্গে সামলায়। নতুন করে বানানোর কারণ হিসেবে OPC Foundation যা বলে তার মধ্যে আছে: Microsoft-এর COM/DCOM-এর চেয়ে cross-platform ব্যবস্থাকে বেশি গুরুত্ব দেওয়া, Microsoft ছাড়া অন্য সিস্টেম আর এমবেডেড যন্ত্রেও চালানোর প্রয়োজন, আর ফায়ারওয়াল পেরিয়ে নিরাপদে সংযোগ করার প্রয়োজন1।

OPC UA-এর স্পেসিফিকেশন IEC-তেও IEC 62541 সিরিজের মানদণ্ড হিসেবে আছে2। যোগাযোগের পোর্ট হিসেবে IANA-তে 4840/TCP, opcua-tcp নামে নিবন্ধিত3।

OPC Classic আর OPC UA-এর পার্থক্যএই চিত্রে দেখানো হয়েছে যে OPC Classic, Windows-এর COM আর DCOM-এর ওপর DA, A&E ও HDA-এর আলাদা স্পেসিফিকেশনে ভাগ করা, আর OPC UA সেগুলোর কাজ প্ল্যাটফর্মের ওপর নির্ভর না করা একটি স্পেসিফিকেশনে একত্র করেছে।কাজগুলো একত্র করেOPC ClassicCOM/DCOM (Windows)-এর ওপর চলেDA, A&E ও HDA-তে ভাগ করা স্পেসিফিকেশনOPC UA (2008)নির্দিষ্ট প্ল্যাটফর্মের ওপর নির্ভর করে নাIEC 62541 হিসেবে মানদণ্ড

চিত্র 1: OPC Classic হলো COM/DCOM-এর ওপর আলাদা আলাদা স্পেসিফিকেশন, আর OPC UA সেগুলো একটিতে একত্র করেছে।

বিদ্যমান যন্ত্রে যদি শুধু OPC DA সার্ভার থাকে, তবে COM/DCOM ব্যবহারকারী দিকের ব্যবস্থা লাগবে। এই নিবন্ধ শুধু OPC UA নিয়ে।

চিত্রে, টানা রেখা সবসময় সত্য এমন সম্পর্ককে এবং ভাঙা রেখা শর্তসাপেক্ষ সম্পর্ককে নির্দেশ করে (শর্তগুলো বিস্তারিত পাতায় প্রতিটি সম্পর্কের ব্যাখ্যায় আছে)। সম্পর্কের সম্পূর্ণ তালিকা (মোট 13, প্রমাণ ও নিশ্চয়তার মাত্রাসহ) এবং প্রধান ধারণাগুলোর সংজ্ঞা জ্ঞান মানচিত্রের বিস্তারিত পাতায় সংগ্রহ করা আছে (জাপানি ভাষায়)। তথ্য: JSON-LD / Turtle

যে কনফিগারেশনে পরীক্ষা করেছি

এই কনফিগারেশনে চালিয়ে দেখেছি।

ভূমিকা যা ব্যবহার করেছি
ক্লায়েন্ট C#, .NET 10 SDK 10.0.114, NuGet প্যাকেজ OPCFoundation.NetStandard.Opc.Ua.Client 2.0.1
সার্ভার Python 3.13 আর asyncua 2.1.0 দিয়ে বানানো সিমুলেটেড যন্ত্র (একই PC-র 4840 পোর্ট)
OS Linux (Windows-এ চালিয়ে পরীক্ষা করিনি)

ক্লায়েন্টের লাইব্রেরি হলো OPC Foundation-এর প্রকাশ করা .NET বাস্তবায়ন। 2.0 লাইনের ব্যবহার একই রিপোজিটরির Getting started-এ দেওয়া লেখার ধরন অনুযায়ী রেখেছি4।

যে কনফিগারেশনে পরীক্ষা করেছিএই চিত্রে দেখানো হয়েছে যে C# ক্লায়েন্ট OPC Foundation-এর .NET লাইব্রেরি ব্যবহার করে, 4840 পোর্টে অপেক্ষারত asyncua-র সিমুলেটেড যন্ত্রের সার্ভারে এনক্রিপ্ট করা সংযোগে যুক্ত হয়।opc.tcp, SignAndEncryptC# ক্লায়েন্ট (LineCollector)সিমুলেটেড যন্ত্রের সার্ভার (asyncua)OPC Foundation-এর .NET লাইব্রেরি 2.0.1Line1-এর 4টি ভেরিয়েবল

চিত্র 2: একই PC-র ভেতরে, C# ক্লায়েন্ট থেকে সিমুলেটেড যন্ত্রের সার্ভারে সংযোগ করেছি।

সিমুলেটেড যন্ত্রের সার্ভার

যন্ত্রের বদলে asyncua দিয়ে একটি ছোট সার্ভার বানিয়েছি5। Line1 নামের অবজেক্টের নিচে চারটি ভেরিয়েবল রেখেছি: তাপমাত্রা (Temperature), উৎপাদন সংখ্যা (PartCount), চালু আছে কি না (Running) আর সেটপয়েন্ট (Setpoint)। তাপমাত্রা প্রতি 0.5 সেকেন্ডে, আর উৎপাদন সংখ্যা প্রতি 2 সেকেন্ডে বদলায়। নিরাপত্তার জন্য দুটি বিকল্প রেখেছি: এনক্রিপশন ছাড়া (None), আর সাইনিং ও এনক্রিপশনসহ (Basic256Sha256-এর SignAndEncrypt)।

# পরীক্ষার জন্য সিমুলেটেড যন্ত্র। এটি আসল যন্ত্র বা PLC-এর বিকল্প নয়।
import asyncio, math, random, socket
from pathlib import Path
from cryptography.x509.oid import ExtendedKeyUsageOID
from asyncua import Server, ua
from asyncua.crypto.cert_gen import setup_self_signed_certificate

HERE = Path(__file__).parent
APP_URI = "urn:komurasoft:demo-plc"


async def main():
    key, cert = HERE / "server_key.pem", HERE / "server_cert.der"
    await setup_self_signed_certificate(
        key, cert, APP_URI, socket.gethostname(),
        [ExtendedKeyUsageOID.SERVER_AUTH], {"commonName": "DemoPlcServer"})

    server = Server()
    await server.init()
    server.set_endpoint("opc.tcp://0.0.0.0:4840/demo/")
    server.set_server_name("DemoPlcServer")
    await server.set_application_uri(APP_URI)
    server.set_security_policy([
        ua.SecurityPolicyType.NoSecurity,
        ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
    ])
    await server.load_certificate(str(cert))
    await server.load_private_key(str(key))

    ns = await server.register_namespace("urn:komurasoft:demo-plc:line1")
    line1 = await server.nodes.objects.add_object(ua.NodeId("Line1", ns), "Line1")
    temperature = await line1.add_variable(ua.NodeId("Line1.Temperature", ns), "Temperature", 25.0)
    part_count = await line1.add_variable(
        ua.NodeId("Line1.PartCount", ns), "PartCount", ua.Variant(0, ua.VariantType.UInt32))
    await line1.add_variable(ua.NodeId("Line1.Running", ns), "Running", True)
    setpoint = await line1.add_variable(ua.NodeId("Line1.Setpoint", ns), "Setpoint", 30.0)
    await setpoint.set_writable()

    async with server:
        print("listening", flush=True)
        t, count = 0, 0
        while True:
            await asyncio.sleep(0.5)
            t += 1
            value = 25.0 + 2.0 * math.sin(t / 4) + random.uniform(-0.05, 0.05)
            await temperature.write_value(round(value, 2))
            if t % 4 == 0:
                count += 1
                await part_count.write_value(ua.Variant(count, ua.VariantType.UInt32))


asyncio.run(main())

এই সার্ভার সংযোগকারী ক্লায়েন্টের সার্টিফিকেট যাচাই না করেই গ্রহণ করে। এটি পরীক্ষার সেটিং, আর আসল যন্ত্রের আচরণ এর থেকে আলাদা।

C# ক্লায়েন্ট

প্রজেক্ট ফাইলে এই দুটি প্যাকেজ যোগ করেছি।

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="2.0.1" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
  </ItemGroup>

</Project>

ক্লায়েন্ট পরপর সংযোগ, ব্রাউজ, পড়া, লেখা আর subscription করে। প্রতিটি অংশের অর্থ পরের অনুচ্ছেদগুলোতে একে একে ব্যাখ্যা করা হয়েছে।

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Client.Subscriptions;
using Opc.Ua.Client.Subscriptions.Streaming;
using MonitoredItemOptions = Opc.Ua.Client.Subscriptions.MonitoredItems.MonitoredItemOptions;

string url = args.Length > 0 ? args[0] : "opc.tcp://localhost:4840/demo/";
int notifications = args.Length > 1 ? int.Parse(args[1]) : 6;
const string LineNamespace = "urn:komurasoft:demo-plc:line1";

HostApplicationBuilder builder = Host.CreateApplicationBuilder();
builder.Logging.SetMinimumLevel(LogLevel.Warning);

builder.Services
    .AddOpcUa()
    .AddClient(options =>
    {
        options.ApplicationName = "LineCollector";
        options.ApplicationUri = "urn:localhost:LineCollector";
        options.ProductUri = "urn:komurasoft:LineCollector";
        options.PkiRoot = Path.Combine(AppContext.BaseDirectory, "pki");
    })
    .AddDiscoveryAndConnect(options =>
    {
        options.DiscoveryUrl = url;
        options.SecurityMode = MessageSecurityMode.SignAndEncrypt;
        options.SecurityPolicyUri = SecurityPolicies.Basic256Sha256;
    });

using IHost host = builder.Build();
await host.StartAsync();
using var timeout = new CancellationTokenSource(TimeSpan.FromMinutes(2));
CancellationToken ct = timeout.Token;

try
{
    var connect = host.Services
        .GetRequiredService<Func<CancellationToken, Task<ManagedSession>>>();
    ManagedSession session = await connect(ct);
    await using (session)
    {
        Console.WriteLine($"接続: {session.ConfiguredEndpoint?.EndpointUrl}");

        // নেমস্পেস ইনডেক্স সার্ভার ঠিক করে। URI থেকে ইনডেক্স বের করে NodeId বানাও
        ushort ns = (ushort)session.NamespaceUris.GetIndex(LineNamespace);
        var line1 = new NodeId("Line1", ns);
        var temperature = new NodeId("Line1.Temperature", ns);
        var partCount = new NodeId("Line1.PartCount", ns);
        var setpoint = new NodeId("Line1.Setpoint", ns);

        // Browse: Line1-এর নিচের ভেরিয়েবলগুলোর তালিকা করো
        var browser = new Browser(session)
        {
            BrowseDirection = BrowseDirection.Forward,
            ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
            IncludeSubtypes = true,
            NodeClassMask = (uint)NodeClass.Variable,
        };
        Console.WriteLine("Line1 の変数:");
        foreach (ReferenceDescription child in await browser.BrowseAsync(line1, ct))
        {
            Console.WriteLine($"  {child.DisplayName}  {child.NodeId}");
        }

        // Read: শুধু মান নয়, স্ট্যাটাস আর দুটি টাইমস্ট্যাম্পও দেখো
        DataValue t = await session.ReadValueAsync(temperature, ct);
        Console.WriteLine($"Temperature = {t.WrappedValue}  状態 {t.StatusCode}");
        Console.WriteLine($"  Source {Hms(t.SourceTimestamp)} / Server {Hms(t.ServerTimestamp)}");

        // নেই এমন নোড পড়লে মানের বদলে Bad স্ট্যাটাস ফেরে
        try
        {
            await session.ReadValueAsync(new NodeId("Line1.Pressure", ns), ct);
        }
        catch (ServiceResultException ex)
        {
            Console.WriteLine($"Line1.Pressure の読み取り: {ex.StatusCode}");
        }

        // Write: Setpoint-কে 32.5 করো
        var write = new WriteValue
        {
            NodeId = setpoint,
            AttributeId = Attributes.Value,
            Value = new DataValue(new Variant(32.5)),
        };
        WriteResponse wr = await session.WriteAsync(null, new[] { write }, ct);
        Console.WriteLine($"Setpoint の書き込み: {wr.Results[0]}");

        // Subscribe: সার্ভারকে প্রতি 500 ms-এ স্যাম্পলিং করতে বলো আর পরিবর্তন জানাতে বলো
        Console.WriteLine($"購読({notifications}件まで):");
        await foreach (DataValueChange change in session.DefaultStreaming
            .SubscribeDataChangesAsync(new[] { temperature, partCount }, options: new MonitoredItemOptions
            {
                SamplingInterval = TimeSpan.FromMilliseconds(500),
                QueueSize = 5,
            }, ct: ct)
            .TakeAsync(notifications)
            .WithCancellation(ct))
        {
            DataValue v = change.Value;
            string name = change.MonitoredItem?.Name.Split("s=")[^1] ?? "?";
            Console.WriteLine($"  {Hms(v.SourceTimestamp)}  {name,-17} {v.WrappedValue,6}  {v.StatusCode}");
        }
    }
}
catch (ServiceResultException ex)
{
    Console.Error.WriteLine($"OPC UA エラー {ex.StatusCode}: {ex.Message}");
    Environment.ExitCode = 1;
}
finally
{
    await host.StopAsync();
}

static string Hms(DateTimeUtc time) => time.ToDateTime().ToString("HH:mm:ss.fff");

প্রথমবার চালানোর সময় সংযোগ হয়নি। কারণটি “সার্টিফিকেট দিয়ে সংযোগের অনুমতি” অনুচ্ছেদে ব্যাখ্যা করা হয়েছে। সার্ভারের সার্টিফিকেট বিশ্বাস করার পরের আউটপুট এরকম। লাইব্রেরির সতর্কবার্তার লগ বাদ দিয়েছি।

接続: opc.tcp://localhost:4840/demo/
Line1 の変数:
  Temperature  ns=2;s=Line1.Temperature
  PartCount  ns=2;s=Line1.PartCount
  Running  ns=2;s=Line1.Running
  Setpoint  ns=2;s=Line1.Setpoint
Temperature = 23.09  状態 Good [0x00000000]
  Source 13:40:51.302 / Server 13:40:51.302
Line1.Pressure の読み取り: BadNodeIdUnknown [0x80340000]
Setpoint の書き込み: Good [0x00000000]
購読(6件まで):
  13:40:51.302  Line1.Temperature  23.09  Good [0x00000000]
  13:40:50.801  Line1.PartCount       67  Good [0x00000000]
  13:40:51.802  Line1.Temperature  23.05  Good [0x00000000]
  13:40:52.304  Line1.Temperature  23.07  Good [0x00000000]
  13:40:52.806  Line1.Temperature   23.2  Good [0x00000000]
  13:40:52.806  Line1.PartCount       68  Good [0x00000000]

সময়গুলো UTC-তে।

যন্ত্রের ডেটা address space-এর নোড হিসেবে দেখা যায়

OPC UA সার্ভার নিজের কাছে থাকা ডেটা নোডের একটি সমষ্টি হিসেবে প্রকাশ করে। এই সমষ্টিকে address space বলে। নোডের নানা ধরন আছে, যেমন ফোল্ডার বা যন্ত্রকে বোঝানো অবজেক্ট আর মান ধারণ করা ভেরিয়েবল, আর নোডগুলো পরস্পরের সঙ্গে রেফারেন্স দিয়ে যুক্ত। ক্লায়েন্ট Browse সার্ভিস দিয়ে রেফারেন্স অনুসরণ করে কোন কোন নোড আছে তা খুঁজে বের করে6।

ওপরের আউটপুটে Line1 থেকে স্তরভিত্তিক রেফারেন্স অনুসরণ করে চারটি ভেরিয়েবল পাওয়া গেছে।

সিমুলেটেড যন্ত্রের address spaceএই চিত্রে দেখানো হয়েছে যে Objects ফোল্ডারের নিচে Line1 অবজেক্ট আছে, আর তার নিচে Temperature, PartCount, Running ও Setpoint নামের চারটি ভেরিয়েবল আছে।ObjectsLine1 (অবজেক্ট)Temperature (ভেরিয়েবল)PartCount (ভেরিয়েবল)Running (ভেরিয়েবল)Setpoint (ভেরিয়েবল, লেখা যায়)

চিত্র 3: সিমুলেটেড যন্ত্রের address space। ক্লায়েন্ট Browse দিয়ে রেফারেন্স অনুসরণ করে নোড খুঁজে পায়।

NodeId তৈরি হয় নেমস্পেস আর আইডেন্টিফায়ার দিয়ে

নোডকে NodeId দিয়ে চিহ্নিত করা হয়। আউটপুটের ns=2;s=Line1.Temperature বোঝায় যে নেমস্পেসের ইনডেক্স 2, আর আইডেন্টিফায়ার হলো স্ট্রিং Line1.Temperature।

নেমস্পেস আসলে একটি URI। স্পেসিফিকেশন অনুযায়ী সার্ভিসের ভেতরে নেমস্পেসের URI একটি সংখ্যা দিয়ে বোঝানো হয়, আর সেই সংখ্যা হলো সার্ভারের NamespaceArray-তে তার অবস্থান। ইনডেক্স 0 হলো OPC UA-এর নেমস্পেস http://opcfoundation.org/UA/7।

তাই ইনডেক্সের সংখ্যা কোডে লিখে না রেখে, URI থেকে ইনডেক্স বের করুন। ওপরের কোডে session.NamespaceUris.GetIndex(LineNamespace) দিয়ে URI থেকে 2 বের করে, তা থেকে NodeId বানানো হয়েছে।

নেমস্পেস URI থেকে NodeId বানানোর ধাপএই চিত্রে দেখানো হয়েছে যে ক্লায়েন্ট নেমস্পেসের URI সার্ভারের NamespaceArray-তে খুঁজে ইনডেক্স পায়, আর সেই ইনডেক্সের সঙ্গে আইডেন্টিফায়ার জুড়ে NodeId বানায়।নেমস্পেসের URIসার্ভারের NamespaceArrayইনডেক্স (এই উদাহরণে 2)NodeId ns=2;s=Line1.Temperatureআইডেন্টিফায়ার Line1.Temperature

চিত্র 4: নেমস্পেসের ইনডেক্স URI থেকে বের করে আইডেন্টিফায়ারের সঙ্গে জুড়ে NodeId বানানো হয়।

পড়া ও লেখায় মানের সঙ্গে স্ট্যাটাস আর টাইমস্ট্যাম্প ফেরে

ভেরিয়েবলের মান Read আর Write সার্ভিস দিয়ে পড়া ও লেখা হয়8। পড়ার সময় শুধু মান ফেরে না। DataValue নামের কাঠামোতে মান, স্ট্যাটাস কোড, সোর্স টাইমস্ট্যাম্প আর সার্ভার টাইমস্ট্যাম্প ফেরে9।

বিষয় অর্থ
মান ভেরিয়েবলের মান। স্ট্যাটাস কোড ত্রুটি দেখালে মান উপেক্ষা করা হয়, আর সার্ভার এটিকে null করে
স্ট্যাটাস কোড (StatusCode) সার্ভার সেই মান পেতে ও দিতে পেরেছে কি না
SourceTimestamp ডেটার উৎস মানের সঙ্গে যে সময় জুড়ে দিয়েছে
ServerTimestamp সার্ভার যে সময়ে মান পেয়েছে, বা মানটি সঠিক বলে জেনেছে

স্ট্যাটাস কোডের ওপরের 2টি বিট Good (সফল), Uncertain (আংশিক সফল, ব্যবহারের ধরন অনুযায়ী কাজে না-ও লাগতে পারে) আর Bad (ব্যর্থ) বোঝায়10। আউটপুটের Good [0x00000000] হলো Good।

নেই এমন Line1.Pressure পড়ার সময় মানের বদলে BadNodeIdUnknown [0x80340000] ফিরেছে। এই লাইব্রেরির ReadValueAsync স্ট্যাটাস Bad হলে ব্যতিক্রম (exception) ছোড়ে4। মান রেকর্ড করার ব্যবস্থায় মানের পাশাপাশি স্ট্যাটাস কোডও রেখে দিলে, পরে আলাদা করা যায় কোন মানগুলো Bad থাকার সময় রেকর্ড হয়েছিল।

DataValue-এর ভেতরে কী থাকেএই চিত্রে দেখানো হয়েছে যে পড়া বা বিজ্ঞপ্তিতে ফেরা DataValue চারটি জিনিস ধারণ করে: মান, স্ট্যাটাস কোড, সোর্স টাইমস্ট্যাম্প আর সার্ভার টাইমস্ট্যাম্প, আর স্ট্যাটাস কোড Bad হলে মান উপেক্ষা করা হয়।Bad হলেDataValueমানস্ট্যাটাস কোডSourceTimestamp (উৎসের সময়)ServerTimestamp (সার্ভারের সময়)মান উপেক্ষা করুন

চিত্র 5: পড়ার ফলাফলে শুধু মান নয়, স্ট্যাটাস কোড আর দুটি টাইমস্ট্যাম্পও থাকে।

লেখার সময় Setpoint-এ 32.5 লিখেছি, আর ফলাফলের স্ট্যাটাস কোড হিসেবে Good ফিরেছে। কোন ভেরিয়েবল লেখা যাবে, তা সার্ভার ঠিক করে। এই সিমুলেটেড সার্ভারে শুধু Setpoint লেখা যায়। যন্ত্রের সেটিং বাইরে থেকে বদলাতে দেওয়া হবে কি না, তা যন্ত্রের নিরাপত্তা নকশার সঙ্গে যুক্ত, তাই এই নিবন্ধের পরিধিতে তা নেই।

পরিবর্তন জানিয়ে দেওয়া: subscription আর MonitoredItem

মানের পরিবর্তন অনুসরণ করতে ক্লায়েন্ট নির্দিষ্ট ব্যবধানে বারবার Read করতে পারে। OPC UA-তে এর বাইরে আরেকটি ব্যবস্থা আছে, যেখানে মানের পর্যবেক্ষণ সার্ভারের হাতে ছেড়ে দিয়ে পরিবর্তন জানিয়ে দিতে বলা হয়। সেটিই subscription আর MonitoredItem।

MonitoredItem হলো পর্যবেক্ষণের একটি লক্ষ্য, আর এর একটি sampling interval থাকে। Sampling interval হলো সবচেয়ে দ্রুত যে ব্যবধানে সার্ভার উৎস থেকে মান স্যাম্পল করে, আর স্পেসিফিকেশন একে “best effort” চক্র বলে11। স্যাম্পল ফিল্টারের শর্ত পূরণ করলে একটি বিজ্ঞপ্তি তৈরি হয়। ফিল্টার না দিলে, মান বা স্ট্যাটাস বদলালে বিজ্ঞপ্তি আসে12।

বিজ্ঞপ্তি প্রথমে MonitoredItem-এর কিউতে যায়। কিউ ভরে গেলে পুরোনো আর নতুনের মধ্যে কোনটি ফেলে দেওয়া হবে তা আগে থেকে ঠিক করা থাকে, আর কিউর আকার 2 বা তার বেশি হলে, ফেলে দেওয়ার ইঙ্গিত দেওয়া Overflow বিট স্ট্যাটাস কোডে সেট হয়13।

Subscription একাধিক MonitoredItem একসঙ্গে রাখে, আর প্রতিটি publishing interval-এ এখনো না পাঠানো বিজ্ঞপ্তিগুলো ক্লায়েন্টকে পাঠায়। পাঠানোর মতো বিজ্ঞপ্তি না থাকা চক্র পরপর চলতে থাকলে, subscription সক্রিয় আছে তা জানাতে keep-alive পাঠায়14।

Subscription আর MonitoredItem-এর প্রবাহএই চিত্রে দেখানো হয়েছে যে MonitoredItem sampling interval-এ উৎসের মান স্যাম্পল করে, ফিল্টার পেরোনো বিজ্ঞপ্তি কিউতে রাখে, subscription সেগুলো publishing interval-এ একসঙ্গে ক্লায়েন্টকে পাঠায়, আর বিজ্ঞপ্তি না থাকলে keep-alive পাঠায়।Sampling intervalPublishing intervalবিজ্ঞপ্তি না থাকলেউৎস (যন্ত্রের মান)MonitoredItemফিল্টার (ডিফল্ট: মান বা স্ট্যাটাসের পরিবর্তন)কিউ (ভরে গেলে Overflow)Subscriptionক্লায়েন্টKeep-alive

চিত্র 6: MonitoredItem স্যাম্পল করে কিউতে জমায়, আর subscription সেগুলো একসঙ্গে ক্লায়েন্টকে পাঠায়।

ওপরের কোডে Temperature আর PartCount-কে 500 মিলিসেকেন্ডের sampling interval আর 5 আকারের কিউ দিয়ে subscribe করেছি15। আউটপুটে তাপমাত্রা প্রায় প্রতি 0.5 সেকেন্ডে, আর উৎপাদন সংখ্যা প্রায় প্রতি 2 সেকেন্ডে আসছে। প্রথম 2টি বিজ্ঞপ্তি ছিল subscription শুরুর মুহূর্তে প্রতিটি ভেরিয়েবলের কাছে থাকা মান। উৎপাদন সংখ্যার 13:40:50.801 হলো subscription শুরুর আগে মান বদলানোর সময়। বিজ্ঞপ্তির সময় হিসেবে সোর্স টাইমস্ট্যাম্প দেখানো হয়েছে, তাই বিজ্ঞপ্তি পাওয়ার সময় নয়, মান বদলানোর সময় দেখা যায়।

বারবার পড়া আর subscription: কোনটি কখন

বারবার পড়ার পদ্ধতিতে ব্যবধান ক্লায়েন্টের দিক থেকে ঠিক করা যায়, আর ব্যবস্থাটি সরল। তার বদলে মান না বদলালেও প্রতিবার অনুরোধ আর উত্তর আসা-যাওয়া করে, আর ব্যবধানের চেয়ে ছোট পরিবর্তন চোখ এড়িয়ে যায়। Subscription-এ সার্ভার স্যাম্পল করে শুধু পরিবর্তন পাঠায়, তাই কম বদলানো মানের ক্ষেত্রেও যোগাযোগ সহজে বাড়ে না। তবে subscription-এও sampling interval-এর চেয়ে ছোট পরিবর্তন না জানানো হতে পারে। স্পেসিফিকেশন নির্ধারিত ব্যবধানের চেয়ে দ্রুত স্যাম্পল করার অনুমতি দেয়, কিন্তু তা বাধ্যতামূলক করে না11।

বারবার পড়া আর subscription-এর পার্থক্যএই চিত্রে দেখানো হয়েছে যে বারবার পড়ার পদ্ধতিতে ক্লায়েন্ট ব্যবধান ঠিক করে প্রতিবার অনুরোধ করে, subscription-এ সার্ভার sampling interval-এ স্যাম্পল করে শুধু পরিবর্তন পাঠায়, আর দুটিতেই ব্যবধানের চেয়ে ছোট পরিবর্তন ধরা না পড়তে পারে।মানের পরিবর্তন অনুসরণ করাবারবার পড়াSubscribe করাক্লায়েন্ট ব্যবধান ঠিক করে প্রতিবার অনুরোধ করেসার্ভার স্যাম্পল করে শুধু পরিবর্তন পাঠায়ব্যবধানের চেয়ে ছোট পরিবর্তন ধরা না পড়তে পারে

চিত্র 7: দুই পদ্ধতিতেই ব্যবধানের চেয়ে ছোট পরিবর্তন ধরা না পড়তে পারে।

সার্টিফিকেট দিয়ে সংযোগের অনুমতি

OPC UA সংযোগে বার্তার সুরক্ষার মাত্রা MessageSecurityMode দিয়ে বাছা হয়। মানগুলো হলো: সুরক্ষা না দেওয়া None, শুধু সাইন করা Sign, আর সাইন করে এনক্রিপ্ট করা SignAndEncrypt16। সাইনিং ও এনক্রিপশনে ব্যবহৃত অ্যালগরিদমের সমন্বয় security policy দিয়ে ঠিক হয়, আর এই নিবন্ধে Basic256Sha256 ব্যবহার করেছি।

সাইনিং ও এনক্রিপশনে প্রতিটি অ্যাপ্লিকেশনের নিজস্ব সার্টিফিকেট ব্যবহৃত হয়। ক্লায়েন্ট আর সার্ভার পরস্পরের সার্টিফিকেট যাচাই করে, আর যাকে বিশ্বাস করে না তার সঙ্গে সংযোগ প্রত্যাখ্যান করে। OPC Foundation-এর .NET লাইব্রেরি দিয়ে বানানো সার্ভার ডিফল্টভাবে এনক্রিপশনহীন None পলিসি দেয় না4।

প্রথম সংযোগ BadCertificateUntrusted-এ আটকে গেল

প্রথমবার চালানোর সময় ক্লায়েন্ট সার্ভারের সার্টিফিকেট বিশ্বাস করত না, তাই সংযোগ প্রত্যাখ্যাত হয়। আউটপুটের একটি অংশ:

fail: Opc.Ua.CertificateValidationCore[91]
      Certificate [Subject=CN=DemoPlcServer, CN=urn:komurasoft:demo-plc, Thumbprint=4E236DDA629FE2AB32D185BF681609FD6C525363, NotBefore=2026-11-01, NotAfter=2027-11-01, KeyAlgorithm=1.2.840.113549.1.1.1] validation failed with suppressible errors but was rejected. Reason=Id: BadCertificateUntrusted
...
OPC UA エラー BadCertificateUntrusted [0x801A0000]: [801A0000] (BadCertificateUntrusted) 'Could not verify security on OpenSecureChannel response.'

এই লাইব্রেরি প্রত্যাখ্যাত সার্টিফিকেট rejected স্টোরে সংরক্ষণ করে। অ্যাডমিনিস্ট্রেটর সেখান থেকে trusted স্টোরে সরালে, লাইব্রেরি সেই পক্ষকে বিশ্বাস করতে শুরু করে17। এবার pki/rejected/certs-এ থাকা সার্ভারের সার্টিফিকেট pki/trusted/certs-এ সরিয়ে আবার চালালাম, আর সংযোগ হলো। সরানোর আগে থাম্বপ্রিন্ট, যা ফাইলের নামেও থাকে, সার্ভারের অ্যাডমিনিস্ট্রেটরের সঙ্গে মিলিয়ে দেখুন4।

সার্টিফিকেট বিশ্বাস করা পর্যন্ত ধাপএই চিত্রে দেখানো হয়েছে যে প্রথম সংযোগে ক্লায়েন্ট সার্ভারের সার্টিফিকেট প্রত্যাখ্যান করে rejected স্টোরে সংরক্ষণ করে, আর থাম্বপ্রিন্ট মিলিয়ে trusted স্টোরে সরালে পরের সংযোগে বিশ্বাস করে সংযোগ করতে পারে।প্রথম সংযোগBadCertificateUntrustedসার্টিফিকেট rejected স্টোরে সংরক্ষণসার্ভারের অ্যাডমিনিস্ট্রেটরের সঙ্গে থাম্বপ্রিন্ট মেলানোtrusted স্টোরে সরানোপরের সংযোগে বিশ্বাস করে সংযোগ

চিত্র 8: প্রত্যাখ্যাত সার্টিফিকেট যাচাই করে trusted-এ সরালে, ক্লায়েন্ট সেই পক্ষকে বিশ্বাস করে।

বিশ্বাস না করা সার্টিফিকেট স্বয়ংক্রিয়ভাবে গ্রহণ করার AutoAcceptUntrustedCertificates নামের সেটিংও আছে। এর ডিফল্ট false, আর লাইব্রেরির ডকুমেন্টেশন বলে যে ডেভেলপমেন্ট পরিবেশে এটি কাজে লাগে, কিন্তু প্রোডাকশনে ব্যবহার করা উচিত নয়17।

লগের NotAfter=2027-11-01 হলো সিমুলেটেড সার্ভারের সার্টিফিকেটের মেয়াদ শেষের তারিখ। এটি asyncua-র ফাংশন দিয়ে বানানো স্ব-স্বাক্ষরিত সার্টিফিকেট, যার মেয়াদ বানানোর দিন থেকে 1 বছর পর শেষ হয়। যন্ত্রের সার্টিফিকেটেরও মেয়াদ থাকে, তাই মেয়াদ শেষ হওয়ার আগে সেটি বদলে অপর পক্ষকে বিশ্বাস করানোর পদ্ধতি পরিচালনার অংশ হিসেবে ঠিক করে রাখুন। Windows সার্টিফিকেট স্টোর কীভাবে সামলাবেন, তা “Windows সার্টিফিকেট স্টোরের বাস্তব নির্দেশিকা“-এ লেখা আছে।

ব্যবহারকারীর প্রমাণীকরণ

সার্টিফিকেট দিয়ে যাচাই করা হয় অ্যাপ্লিকেশনগুলো পরস্পরকে। এর বাইরে, সেশন খোলার সময় ব্যবহারকারীকে বোঝানো একটি টোকেন দেওয়া হয়। স্পেসিফিকেশনে চার ধরন আছে: anonymous, ব্যবহারকারীর নাম ও পাসওয়ার্ড, X.509 সার্টিফিকেট, আর বাইরে থেকে জারি করা টোকেন18। এবারের ক্লায়েন্ট anonymous হিসেবে সংযোগ করেছে। সার্ভার কোন টোকেন গ্রহণ করে, তা সার্ভারের এন্ডপয়েন্টের তথ্যে থাকে19।

মাঠপর্যায়ে ডেটা সংগ্রহে যেখানে সমস্যা হয়

এখান থেকে, যন্ত্রের ডেটা সংগ্রহের ব্যবস্থায় প্রায়ই যে সমস্যাগুলো ঘটে, সেগুলো এবারের পরীক্ষা আর স্পেসিফিকেশনের ভিত্তিতে তুলে ধরা হয়েছে।

সার্ভার বন্ধ থাকার সময়ের মান আসে না

Subscription চলার মাঝে সার্ভার থামিয়ে, প্রায় 15 সেকেন্ড পরে আবার চালু করেছি। এই লাইব্রেরির ManagedSession সংযোগ বিচ্ছিন্ন হলে স্বয়ংক্রিয়ভাবে পুনঃসংযোগ করে20। সার্ভার বন্ধ থাকার সময় ক্লায়েন্ট বারবার পুনঃসংযোগের চেষ্টা করছিল।

warn: Opc.Ua.ChannelManager[6]
      Reconnect failed. Endpoint=opc.tcp://localhost:4840/demo/, Attempt=3, Outcome=transient-failure, Status=BadNotConnected, ErrorMessage=Could not connect to the remote endpoint.

সার্ভার ফিরে এলে বিজ্ঞপ্তিও ফিরে এল। Subscription-এর আউটপুটের একটি অংশ:

  13:41:13.364  Line1.Temperature  25.61  Good [0x00000000]
  13:41:13.865  Line1.Temperature  25.12  Good [0x00000000]
  13:41:34.285  Line1.Temperature  26.55  Good [0x00000000]
  13:41:33.784  Line1.PartCount        2  Good [0x00000000]
  13:41:34.786  Line1.Temperature  26.16  Good [0x00000000]

13:41:13 থেকে 13:41:34 পর্যন্ত একটি মানও আসেনি। উৎপাদন সংখ্যা 78 থেকে 2-এ ফিরে গেছে। এর কারণ, সিমুলেটেড সার্ভার আবার চালু করায় সেটি 0 থেকে গোনা শুরু করেছে।

এই উদাহরণে সার্ভারই বন্ধ ছিল, তাই ওই সময়ের মান কোথাও থেকে যায়নি। পুনঃসংযোগের ব্যবস্থা সংযোগ ফিরিয়ে আনে, কিন্তু বন্ধ থাকার সময়ের মান পরে পূরণ করে দেয় না।

শুধু যোগাযোগ বিচ্ছিন্ন হয়ে সার্ভার চলতে থাকলে পরিস্থিতি আলাদা। স্পেসিফিকেশনে Republish সার্ভিস আছে, যা দিয়ে না পৌঁছানো বিজ্ঞপ্তির বার্তা সার্ভারের পুনঃপ্রেরণ কিউ থেকে আবার পাঠাতে বলা যায়21। MonitoredItem-এর কিউতেও বিজ্ঞপ্তি জমে, তবে কিউর আকারের বেশি অংশ ফেলে দেওয়া হয়13। এবারের পরীক্ষায় এই অবস্থা পরীক্ষা করিনি। যেকোনো ক্ষেত্রে, কোন সময়ে মান আসেনি তা বোঝার জন্য বিচ্ছিন্ন আর পুনঃসংযোগের সময় রেকর্ডে রেখে দিন। সিরিয়াল যোগাযোগের যন্ত্রে পুনঃসংযোগ আর লগের নকশা “Serial Communication App Pitfalls“-এও আলোচনা করা হয়েছে।

সার্ভার থামালে রেকর্ডএই চিত্রে দেখানো হয়েছে যে subscription চলার সময় সার্ভার থামলে ক্লায়েন্ট বারবার পুনঃসংযোগ করে, সার্ভার ফিরলে বিজ্ঞপ্তিও ফেরে, কিন্তু বন্ধ থাকার সময়ের মান আসে না, তাই বিচ্ছিন্ন আর পুনঃসংযোগের সময় রেকর্ডে রাখা হয়।Subscription চলছেসার্ভার থামেক্লায়েন্ট বারবার পুনঃসংযোগ করেসার্ভার ফেরে, বিজ্ঞপ্তিও ফেরেবন্ধ থাকার সময়ের মান আসে নাবিচ্ছিন্ন আর পুনঃসংযোগের সময় রেকর্ড করুন

চিত্র 9: পুনঃসংযোগে সংযোগ ফেরে, কিন্তু সার্ভার বন্ধ থাকার সময়ের মান আসে না।

কোন টাইমস্ট্যাম্প রেকর্ড করবেন

স্পেসিফিকেশন অনুযায়ী SourceTimestamp হলো ডেটার উৎস মানের সঙ্গে জুড়ে দেওয়া সময়, যা মান বদলানোর সময় দেখানো উচিত। ServerTimestamp হলো সার্ভার যে সময়ে মান পেয়েছে, বা মানটি সঠিক বলে জেনেছে9। এবারের সিমুলেটেড সার্ভার নিজেই মান তৈরি করে, তাই দুটি সময় একই ছিল।

যন্ত্রে কখন মান বদলেছে জানতে চাইলে SourceTimestamp ব্যবহার করুন। তবে সেই সময় উৎসের ঘড়ি দিয়ে দেওয়া হয়, তাই যন্ত্র বা সার্ভারের ঘড়ি সরে গেলে রেকর্ডও সরে যায়। সংগ্রহ করা ডেটা অন্য রেকর্ডের সঙ্গে মেলাতে হলে, গ্রহণকারী PC-র সময়ও পাশাপাশি রেখে দিলে পরে পার্থক্য যাচাই করা যায়। Windows দিকের সময় সমন্বয় “Windows Time Synchronization (w32time) and Business Systems“-এ লেখা আছে।

Good ছাড়া অন্য স্ট্যাটাসের মান সরাসরি সংখ্যা হিসেবে ব্যবহার করবেন না

স্ট্যাটাস কোড Bad হলে মান উপেক্ষা করার কথা9। Uncertain হলে, ব্যবহারের ধরন অনুযায়ী মানটি কাজে না-ও লাগতে পারে10। গ্রাফ বা হিসাবে ঢোকানোর আগে স্ট্যাটাস কোড দিয়ে বাছাই করুন, আর Good ছাড়া অন্য মান নিয়ে কী করবেন তা ঠিক করে রাখুন। কিউ ভরে গেলে Overflow বিটও স্ট্যাটাস কোডের ভেতরে সেট হয়13। যন্ত্রের অবস্থা স্ক্রিনে কীভাবে দেখাবেন, তা “Best Practices for Checking and Displaying External Device State“-এ আলোচনা করা হয়েছে।

ফায়ারওয়ালে পোর্ট খুলুন

IANA-তে নিবন্ধিত OPC UA-এর পোর্ট হলো 4840/TCP3। তবে সব সার্ভার এই নম্বর ব্যবহার করে না। OPC Foundation-এর .NET নমুনাগুলো 62541-এর মতো পোর্ট ব্যবহার করে4। যন্ত্রের এন্ডপয়েন্টের URL থেকে পোর্ট নম্বর মিলিয়ে দেখে, সেই পোর্টে সংযোগের অনুমতি দিন। সার্ভার Windows-এ চললে সেই Windows ফায়ারওয়ালে, আর মাঝে নেটওয়ার্ক যন্ত্র থাকলে সেই যন্ত্রে অনুমতি দিন। ইনবাউন্ড নিয়ম বানানোর পদ্ধতি “Windows Firewall ও ব্যবসায়িক অ্যাপ“-এ লেখা আছে।

ডেটা সংগ্রহে যেখানে সমস্যা হয়এই চিত্রে যন্ত্রের ডেটা সংগ্রহে সমস্যার জায়গাগুলো দুই ভাগে দেখানো হয়েছে: রেকর্ডের বিষয়বস্তু (সার্ভার বন্ধ থাকার সময়ের মান না আসা, কোন টাইমস্ট্যাম্প রেকর্ড করবেন, Good ছাড়া অন্য মানের ব্যবস্থা) আর সংযোগের প্রস্তুতি (ফায়ারওয়ালের পোর্ট, সার্টিফিকেটের মেয়াদ)।ডেটা সংগ্রহে যেখানে সমস্যা হয়রেকর্ডের বিষয়বস্তুসংযোগের প্রস্তুতিবন্ধ থাকার সময়ের মান আসে নাকোন টাইমস্ট্যাম্পGood ছাড়া অন্য মানফায়ারওয়ালের পোর্টসার্টিফিকেটের মেয়াদ

চিত্র 10: সংযোগ হয়ে যাওয়ার পরও রেকর্ডের ফাঁক, সময়, স্ট্যাটাস, পোর্ট আর সার্টিফিকেট যাচাই করুন।

Modbus/TCP বা নির্মাতার নিজস্ব যোগাযোগের সঙ্গে বাছাই

PLC ও যন্ত্রের সঙ্গে যোগাযোগের জন্য OPC UA ছাড়াও Modbus/TCP, আর PLC নির্মাতার দেওয়া যোগাযোগও আছে।

Modbus-এর স্পেসিফিকেশন ডেটাকে চারটি টেবিলে রাখে: শুধু পড়া যায় এমন 1 বিটের Discrete Input, পড়া-লেখা যায় এমন 1 বিটের Coil, শুধু পড়া যায় এমন 16 বিটের Input Register, আর পড়া-লেখা যায় এমন 16 বিটের Holding Register22। IANA-তে Modbus অ্যাপ্লিকেশন প্রোটোকল (mbap) হিসেবে 502/TCP নিবন্ধিত3।

এই টেবিলে থাকে শুধু বিট আর 16 বিটের শব্দ, তাই কোন ঠিকানায় কোন মান কোন বিন্যাসে আছে, তা যন্ত্রের ডকুমেন্টেশন থেকে মিলিয়ে ক্লায়েন্টের দিকে লিখতে হয়। OPC UA-তে, ওপরে যেমন দেখা গেল, সার্ভার নাম দেওয়া ভেরিয়েবল address space-এ প্রকাশ করে, আর ক্লায়েন্ট Browse দিয়ে সেগুলো জানতে পারে। মানের সঙ্গে স্ট্যাটাস কোড আর টাইমস্ট্যাম্প থাকে, আর সংযোগের জন্য সার্টিফিকেট দিয়ে অনুমতি থাকে।

কোনটি ব্যবহার করবেন, তা প্রায়ই যন্ত্র কী দেয় তার ওপর নির্ভর করে। যন্ত্রে OPC UA সার্ভার থাকলে সেটি ব্যবহার করুন, আর শুধু Modbus/TCP থাকলে ঠিকানার সারণি বানিয়ে পড়ুন। শুধু নির্মাতার যোগাযোগ বা SDK থাকলে, তার ডকুমেন্টেশন অনুসরণ করুন। USB যন্ত্রের সঙ্গে যোগাযোগের পদ্ধতি কীভাবে বাছবেন, তা “How to Work with USB Devices from a Windows App“-এ লেখা আছে।

যন্ত্রের সঙ্গে যোগাযোগ কীভাবে বাছবেনএই চিত্রে দেখানো হয়েছে যে যন্ত্রে OPC UA সার্ভার থাকলে OPC UA দিয়ে ভেরিয়েবল ব্রাউজ করে সংগ্রহ করা হয়, শুধু Modbus/TCP থাকলে ডকুমেন্টেশন থেকে ঠিকানা আর বিন্যাস মিলিয়ে রেজিস্টার পড়া হয়, আর শুধু নির্মাতার যোগাযোগ থাকলে তার ডকুমেন্টেশন অনুসরণ করা হয়।OPC UA সার্ভারশুধু Modbus/TCPশুধু নির্মাতার যোগাযোগযন্ত্র যে যোগাযোগ দেয়কী আছে?ভেরিয়েবল ব্রাউজ করে সংগ্রহডকুমেন্টেশন থেকে ঠিকানা আর বিন্যাস মেলানোনির্মাতার ডকুমেন্টেশন আর SDK অনুসরণরেজিস্টার পড়ে মানে রূপান্তর

চিত্র 11: কী দিয়ে সংগ্রহ করবেন, তা প্রায়ই যন্ত্র কী দেয় তার ওপর নির্ভর করে।

সম্পর্কিত নিবন্ধ

তথ্যসূত্র

  1. OPC Foundation, Classic. OPC Classic-এর COM/DCOM-ভিত্তিক হওয়া, DA, A&E ও HDA স্পেসিফিকেশন, 2008 সালে OPC UA-এর প্রকাশ, আর নতুন করে বানানোর কারণ। ↩ ↩2

  2. IEC, IEC TR 62541-1:2020 OPC Unified Architecture - Part 1: Overview and concepts. OPC UA-এর ধারণা ও সংক্ষিপ্ত পরিচয় নিয়ে IEC 62541 সিরিজের প্রথম অংশ (পরবর্তী সংস্করণে প্রতিস্থাপিত)। ↩

  3. IANA, Service Name and Transport Protocol Port Number Registry. 4840/TCP-তে opcua-tcp আর 502/TCP-তে mbap-এর নিবন্ধন। ↩ ↩2 ↩3

  4. OPC Foundation, UA-.NETStandard 2.0.1: Getting started. 2.0 লাইনের ক্লায়েন্ট লেখার ধরন, Bad হলে ReadValueAsync-এর ব্যতিক্রম ছোড়া, rejected ও trusted স্টোর, সার্ভারের ডিফল্টভাবে None না দেওয়া, আর নমুনার পোর্ট নম্বর। ↩ ↩2 ↩3 ↩4 ↩5

  5. FreeOpcUa, asyncua (PyPI). সিমুলেটেড যন্ত্রের সার্ভারে ব্যবহৃত Python-এর OPC UA লাইব্রেরি। ↩

  6. OPC Foundation, OPC 10000-4 v1.05, 5.9.2 Browse. নোডের রেফারেন্স অনুসরণের সার্ভিস। ↩

  7. OPC Foundation, OPC 10000-3 v1.05, 8.2.2 NamespaceIndex. সার্ভিসের ভেতরে নেমস্পেসের URI সংখ্যা দিয়ে বোঝানো, আর সেই সংখ্যা NamespaceArray-তে অবস্থান হওয়া। ↩

  8. OPC Foundation, OPC 10000-4 v1.05, 5.11 Attribute Service Set. Read আর Write সার্ভিস। ↩

  9. OPC Foundation, OPC 10000-4 v1.05, 7.11 DataValue. মান, স্ট্যাটাস কোড, SourceTimestamp আর ServerTimestamp-এর সংজ্ঞা। ↩ ↩2 ↩3

  10. OPC Foundation, OPC 10000-4 v1.05, 7.38.1 StatusCode General. ওপরের 2টি বিট দিয়ে বোঝানো Good, Uncertain আর Bad। ↩ ↩2

  11. OPC Foundation, OPC 10000-4 v1.05, 5.13.1.2 Sampling interval. Sampling interval একটি best effort চক্র হওয়া। ↩ ↩2

  12. OPC Foundation, OPC 10000-4 v1.05, 7.22.2 DataChangeFilter. ফিল্টার না থাকলে মান বা স্ট্যাটাস বদলালে বিজ্ঞপ্তি আসা। ↩

  13. OPC Foundation, OPC 10000-4 v1.05, 5.13.1.5 Queue parameters. কিউর আকার, ফেলে দেওয়ার নিয়ম, আর Overflow বিট। ↩ ↩2 ↩3

  14. OPC Foundation, OPC 10000-4 v1.05, 5.14.1.1 Subscription model. Publishing interval আর keep-alive। ↩

  15. OPC Foundation, UA-.NETStandard 2.0.1: Subscriptions and Monitored Items Service Set. SubscribeDataChangesAsync, আর MonitoredItemOptions-এর sampling interval ও কিউর আকার। ↩

  16. OPC Foundation, OPC 10000-4 v1.05, 7.20 MessageSecurityMode. None, Sign আর SignAndEncrypt-এর অর্থ। ↩

  17. OPC Foundation, UA-.NETStandard 2.0.1: Certificates. rejected স্টোর থেকে বিশ্বস্ত স্টোরে সরানোর ব্যবস্থা, আর প্রোডাকশনে AutoAcceptUntrustedCertificates ব্যবহার না করা। ↩ ↩2

  18. OPC Foundation, OPC 10000-4 v1.05, 7.40 UserIdentityToken parameters. চার ধরন: anonymous, ব্যবহারকারীর নাম, X.509 আর জারি করা টোকেন। ↩

  19. OPC Foundation, OPC 10000-4 v1.05, 7.14 EndpointDescription. এন্ডপয়েন্ট যে ব্যবহারকারী টোকেন গ্রহণ করে তার তালিকা (userIdentityTokens)। ↩

  20. OPC Foundation, UA-.NETStandard 2.0.1: Sessions, Reconnection, and Subscription Engines. ManagedSession-এ পুনঃসংযোগের ব্যবস্থা অন্তর্নির্মিত থাকা। ↩

  21. OPC Foundation, OPC 10000-4 v1.05, 5.14.6.1 Republish. Subscription-এর পুনঃপ্রেরণ কিউ থেকে বিজ্ঞপ্তির বার্তা আবার পাঠাতে বলার সার্ভিস। ↩

  22. Modbus-IDA, MODBUS Application Protocol Specification V1.1b (University of Chicago-র সার্ভারে রাখা অনুলিপি). 4.3 অনুচ্ছেদের ডেটা মডেল (Discrete Input, Coil, Input Register, Holding Register)। ↩

কাছাকাছি বিষয়ে গভীরে যেতে একই ট্যাগযুক্ত সাম্প্রতিক নিবন্ধ।

ব্যবহারিক মাল্টিথ্রেডিং সেরা অনুশীলন: .NET সংস্করণ — আরও থ্রেড যোগ করার আগে কী ঠিক করবেন

.NET/C#-এ মাল্টিথ্রেডেড কোড যেন মাঝে মাঝে ক্র্যাশ বা হ্যাং না করে, তার ডিজাইন নিয়ম: নিজে থ্রেড না বানিয়ে Task-এ চড়া, ভাগ করা পরিবর্তনয...

C# ও PowerShell থেকে WMI/CIM ব্যবহার — হার্ডওয়্যার তথ্য, প্রক্রিয়া নজরদারি ও দূরবর্তী অনুসন্ধানের বাস্তব নির্দেশিকা

PC-র সিরিয়াল নম্বর, ডিস্কের খালি জায়গা ও প্রক্রিয়া চালু হওয়া শনাক্তের নিয়মিত উপায় WMI/CIM। Get-CimInstance-এর মতো CIM কমান্ডলেট, পু...

Windows I/O-এর গভীরতা (৪র্থ কিস্তি) — ক্যাশ ম্যানেজার: আপনার WriteFile কখন ডিস্কে পৌঁছায়

Windows-এর ক্যাশ ম্যানেজার চিত্রে ব্যাখ্যা করা ধারাবাহিকের ৪র্থ কিস্তি। ফাইল ম্যাপিং হিসেবে বাস্তবায়িত ক্যাশ, আগে পড়া ও বিলম্বিত লেখা, ...

নেমড পাইপ ব্যবহারিকভাবে — ডিজাইন থেকে নিরাপত্তা পর্যন্ত Windows-এর মানক IPC

Windows-এর মানক আন্তঃপ্রক্রিয়া যোগাযোগ নেমড পাইপের ব্যবহারিক গাইড। প্রাথমিক উৎস থেকে এই নিবন্ধ বাইট ও মেসেজ মোডের পছন্দ, একাধিক ক্লায়েন...

Spurious Wakeup — কন্ডিশন ভেরিয়েবল কেন "নোটিফাই না হয়েও" জাগে এবং Windows-এ সঠিকভাবে কীভাবে অপেক্ষা করবেন

কন্ডিশন ভেরিয়েবলের ওয়েট নোটিফিকেশন না এলেও ফিরতে পারে (spurious wakeup)। এই নিবন্ধ Windows বাস্তবায়ন থেকে ব্যাখ্যা করে স্পেসিফিকেশন কে...

এই বিষয়ের কাছাকাছি টপিক পৃষ্ঠা। নিবন্ধ থেকে শুরু করে সংশ্লিষ্ট সেবা ও অন্য নিবন্ধে যাওয়া যাবে।

এই নিবন্ধ নিচের সেবা পৃষ্ঠাগুলোর সঙ্গে যুক্ত। কাছের প্রবেশপথ থেকে দেখে নিন।

Windows অ্যাপ ডেভেলপমেন্ট

যন্ত্র থেকে ডেটা সংগ্রহ করার Windows অ্যাপ বানাতে চাইলে, subscription-এর সেটিং, পুনঃসংযোগ, আর টাইমস্ট্যাম্প ও স্ট্যাটাস রেকর্ড করা পর্যন্ত, Windows অ্যাপ ডেভেলপমেন্ট হিসেবে এটি নেওয়া যায়।

প্রযুক্তিগত পরামর্শ ও ডিজাইন রিভিউ

OPC UA দিয়ে সংগ্রহ করবেন, নাকি Modbus/TCP বা নির্মাতার নিজস্ব যোগাযোগ ব্যবহার করবেন, আর সার্টিফিকেট কীভাবে পরিচালনা করবেন, তা ঠিক করতে চাইলে প্রযুক্তিগত পরামর্শ ও ডিজাইন রিভিউ হিসেবে এটি নেওয়া যায়।

প্রায়শ জিজ্ঞাসিত প্রশ্ন

এই নিবন্ধের বিষয়ে পরামর্শে প্রায়ই আসা প্রশ্ন।

OPC UA আর OPC Classic (OPC DA)-এর মধ্যে পার্থক্য কী?
OPC Classic হলো Windows-এর COM/DCOM দিয়ে ডেটা আদান-প্রদানের স্পেসিফিকেশন। OPC UA 2008 সালে প্রকাশিত, নির্দিষ্ট কোনো OS-এর ওপর নির্ভর না করা একটি স্পেসিফিকেশন, যা Classic-এর কাজগুলো একসঙ্গে সামলায়। OPC UA-এর ক্লায়েন্ট Windows-এর বাইরেও চলে, আর DCOM-এর সেটিংও লাগে না।
OPC UA দিয়ে মান সংগ্রহ করার সময় নির্দিষ্ট ব্যবধানে পড়লেই কি যথেষ্ট?
মান কম আর ব্যবধান লম্বা হলে পড়েও সংগ্রহ করা যায়। মানের পরিবর্তন অনুসরণ করতে চাইলে, subscription দিয়ে স্যাম্পলিং সার্ভারের হাতে ছেড়ে পরিবর্তন জানিয়ে দিতে বলার উপায়ও আছে। যেকোনো ক্ষেত্রে, মানের সঙ্গে ফেরা স্ট্যাটাস কোড আর টাইমস্ট্যাম্পও রেকর্ড করুন।
সংযোগ করলে BadCertificateUntrusted আসে কেন?
কারণ ক্লায়েন্ট এখনো সার্ভারের সার্টিফিকেটকে বিশ্বাস করে না। OPC Foundation-এর .NET লাইব্রেরি প্রত্যাখ্যাত সার্টিফিকেট rejected স্টোরে সংরক্ষণ করে। সার্টিফিকেটের থাম্বপ্রিন্ট সার্ভারের অ্যাডমিনিস্ট্রেটরের সঙ্গে মিলিয়ে দেখে তারপর trusted স্টোরে সরান। সার্টিফিকেট স্বয়ংক্রিয়ভাবে গ্রহণ করার সেটিং শুধু ডেভেলপমেন্ট পরিবেশে সীমিত রাখুন।
OPC UA-এর পোর্ট নম্বর কত?
IANA-তে 4840/TCP, opcua-tcp নামে নিবন্ধিত। তবে আসল সার্ভার কখনো কখনো অন্য পোর্ট ব্যবহার করে, তাই যন্ত্রের সেটিংয়ে মিলিয়ে দেখুন। সার্ভার Windows-এ চললে Windows ফায়ারওয়ালে, আর মাঝে নেটওয়ার্ক যন্ত্র থাকলে সেই যন্ত্রে, ওই পোর্টে যোগাযোগের অনুমতি দিতে হবে।

লেখকের প্রোফাইল

নিবন্ধের লেখকের পরিচিতি পৃষ্ঠা।

Go Komura

KomuraSoft LLC-এর প্রতিনিধি

Windows সফটওয়্যার ডেভেলপমেন্ট, প্রযুক্তিগত পরামর্শ ও বাগ তদন্তকে কেন্দ্র করে কাজ করেন; বিদ্যমান সম্পদ রয়ে গেছে এমন প্রকল্পে এবং কারণ সহজে চোখে পড়ে না এমন ব্যর্থতার তদন্তে তাঁর বিশেষ শক্তি রয়েছে।

পাবলিক লিঙ্ক

ব্লগে ফিরে যান