OPC UA की शुरुआत ── PLC और equipment का data Windows app में collect करना

· · Windows, OPC UA, Manufacturing, PLC, C#, .NET, Networking, Certificates

X पर पोस्ट करें
संशोधन इतिहास (केवल पहला संस्करण, 1 Nov 2026 को प्रकाशित)
पहला प्रकाशन
इस लेख का हवाला दें(DOI: 10.5281/zenodo.23968408)

यह लेख Zenodo पर संग्रहीत है। नीचे वह DOI है जो हमेशा नवीनतम संस्करण की ओर ले जाता है, और वह DOI भी जो आपके पढ़े जा रहे संस्करण से बँधा है।

Go Komura (2026). OPC UA की शुरुआत ── PLC और equipment का data Windows app में collect करना. KomuraSoft LLC. https://doi.org/10.5281/zenodo.23968408 https://comcomponent.com/hi/blog/opc-ua-windows-data-collection/

DOI (नवीनतम संस्करण)
10.5281/zenodo.23968408
DOI (यह संस्करण)
10.5281/zenodo.23968409

PLC या equipment का data किसी Windows app में collect करते समय, अगर equipment में OPC UA server हो, तो कई बार हर vendor के लिए अलग communication लिखने की ज़रूरत नहीं पड़ती। लेकिन सिर्फ़ connect करके value पढ़ लेना काफ़ी नहीं है। Value के साथ आने वाला status और timestamp, changes notify करने वाला subscription, certificate से connection की अनुमति, और disconnect के बाद वापस आने का तरीका न जानें, तो collect किए data पर बाद में भरोसा नहीं किया जा सकता।

यह article OPC UA के उन हिस्सों को समझाता है जो data collection के लिए ज़रूरी हैं, साथ में C# client को असल में चलाकर मिले results भी हैं। Client के लिए OPC Foundation की .NET library इस्तेमाल की, और दूसरी तरफ़ एक simulated equipment server रखा। किसी specific PLC या equipment पर इसे test नहीं किया है। हर equipment की settings उसी equipment के documentation में confirm करें।

GigE Vision और USB3 Vision cameras से images collect करने की बात “Dropped Frames with GigE Vision and USB3 Vision Cameras” में, और serial communication वाले equipment की बात “Serial Communication App Pitfalls” में है।

OPC UA और OPC Classic में फ़र्क

OPC Classic की specifications, software components के बीच data exchange करने के लिए Windows का COM/DCOM इस्तेमाल करती हैं। Process data के लिए OPC DA, alarms के लिए OPC A&E और history के लिए OPC HDA अलग-अलग specifications के रूप में तय की गई हैं1।

OPC Foundation ने 2008 में OPC UA (Unified Architecture) publish किया। OPC UA किसी specific platform पर निर्भर न रहने वाला service-oriented architecture है, और Classic की हर specification के functions को एक साथ संभालता है। OPC Foundation इसे नए सिरे से बनाने के कारणों में ये बताता है: Microsoft का COM/DCOM की बजाय cross-platform mechanisms को ज़्यादा महत्व देना, Microsoft के अलावा दूसरे systems और embedded devices पर भी चलाने की ज़रूरत, और firewalls के पार सुरक्षित रूप से connect करने की ज़रूरत1।

OPC UA की specification IEC में भी IEC 62541 series के standard के रूप में है2। Communication port के लिए IANA में 4840/TCP, opcua-tcp के नाम से registered है3।

OPC Classic और OPC UA में फ़र्कयह diagram दिखाता है कि OPC Classic, Windows के COM और DCOM पर आधारित है और DA, A&E और HDA की अलग-अलग specifications में बँटा है, जबकि OPC UA उनके functions को किसी platform पर निर्भर न रहने वाली एक specification में समेटता है।functions को एक साथ लाता हैOPC ClassicCOM/DCOM (Windows) पर चलता हैDA, A&E और HDA में बँटी specificationsOPC UA (2008)किसी specific platform पर निर्भर नहींIEC 62541 के रूप में standard

चित्र 1: OPC Classic, COM/DCOM पर बनी अलग-अलग specifications है, और OPC UA उन्हें एक में समेटता है।

अगर मौजूदा equipment में सिर्फ़ OPC DA server है, तो COM/DCOM इस्तेमाल करने वाली तरफ़ का mechanism चाहिए। यह article सिर्फ़ OPC UA को cover करता है।

Diagram में solid line हमेशा लागू रहने वाला relation दिखाती है और dashed line conditional relation दिखाती है (शर्तें detail page पर हर relation के explanation में दी गई हैं)। Relations की पूरी list (कुल 13, evidence और certainty सहित) तथा मुख्य concepts की definitions knowledge map की detail page पर संकलित हैं (जापानी में)। Data: JSON-LD / Turtle

Test किया गया setup

Test के लिए यह setup इस्तेमाल किया।

Role इस्तेमाल की गई चीज़
Client C#, .NET 10 SDK 10.0.114, NuGet package OPCFoundation.NetStandard.Opc.Ua.Client 2.0.1
Server Python 3.13 और asyncua 2.1.0 से बनाया गया simulated equipment (उसी PC का port 4840)
OS Linux (Windows पर run करके test नहीं किया)

Client library, OPC Foundation का publish किया हुआ .NET implementation है। 2.0 line का usage उसी repository के Getting started में दिए तरीके के हिसाब से रखा4।

Test किया गया setupयह diagram दिखाता है कि C# client, OPC Foundation की .NET library इस्तेमाल करके, port 4840 पर listen कर रहे asyncua के simulated equipment server से encrypted connection के साथ connect करता है।opc.tcp, SignAndEncryptC# client (LineCollector)Simulated equipment server (asyncua)OPC Foundation की .NET library 2.0.1Line1 के 4 variables

चित्र 2: एक ही PC के अंदर, C# client से simulated equipment server पर connect किया।

Simulated equipment server

Equipment की जगह asyncua से एक छोटा server बनाया5। Line1 नाम के object के नीचे चार variables रखे हैं: temperature (Temperature), production count (PartCount), running (Running) और setpoint (Setpoint)। Temperature हर 0.5 second में और production count हर 2 second में बदलता है। Security के लिए दो options रखे: बिना encryption (None), और signing के साथ encryption (Basic256Sha256 का SignAndEncrypt)।

# Testing के लिए simulated equipment. यह production equipment या 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())

यह server connect करने वाले client का certificate check किए बिना accept कर लेता है। यह testing वाली setting है, और production equipment का behaviour इससे अलग है।

C# client

Project file में ये दो packages डाले।

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

Client क्रम से connect, browse, read, write और subscribe करता है। हर हिस्से का मतलब अगले sections में एक-एक करके समझाया गया है।

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}");

        // Namespace index server तय करता है। URI से index निकालकर 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 के नीचे के variables की list बनाएँ
        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: सिर्फ़ value नहीं, status और दोनों timestamps भी देखें
        DataValue t = await session.ReadValueAsync(temperature, ct);
        Console.WriteLine($"Temperature = {t.WrappedValue}  状態 {t.StatusCode}");
        Console.WriteLine($"  Source {Hms(t.SourceTimestamp)} / Server {Hms(t.ServerTimestamp)}");

        // जो node मौजूद नहीं, उसे पढ़ने पर value की जगह Bad status आता है
        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: server से हर 500 ms पर sampling करवाएँ और changes notify करवाएँ
        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");

पहली बार चलाने पर connect नहीं हुआ। इसकी वजह “Certificate से connection की अनुमति” वाले section में समझाई गई है। Server का certificate trust करने के बाद का output यह है। Library के warning logs हटा दिए हैं।

接続: 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]

Times UTC में हैं।

Equipment का data address space के nodes के रूप में दिखता है

OPC UA server अपने पास का data nodes के एक collection के रूप में expose करता है। इस collection को address space कहते हैं। Nodes के कई types होते हैं, जैसे folders या equipment को दर्शाने वाले objects, और values रखने वाले variables, और nodes आपस में references से जुड़े होते हैं। Client, Browse service से references follow करके पता करता है कि कौन-कौन से nodes हैं6।

ऊपर के output में Line1 से hierarchical references follow करके चार variables मिले हैं।

Simulated equipment का address spaceयह diagram दिखाता है कि Objects folder के नीचे Line1 object है, और उसके नीचे Temperature, PartCount, Running और Setpoint नाम के चार variables हैं।ObjectsLine1 (object)Temperature (variable)PartCount (variable)Running (variable)Setpoint (variable, writable)

चित्र 3: Simulated equipment का address space। Client, Browse से references follow करके nodes ढूँढता है।

NodeId, namespace और identifier से बनता है

Nodes को NodeId से पहचाना जाता है। Output का ns=2;s=Line1.Temperature बताता है कि namespace index 2 है और identifier string Line1.Temperature है।

Namespace असल में एक URI है। Specification के अनुसार services के अंदर namespace URI को एक number से दर्शाया जाता है, और वह number server के NamespaceArray में उसकी position होता है। Index 0, OPC UA का namespace http://opcfoundation.org/UA/ है7।

इसलिए index का number code में लिखकर रखने की बजाय, URI से index निकालें। ऊपर के code में session.NamespaceUris.GetIndex(LineNamespace) से URI से 2 निकाला गया है, और उससे NodeId बनाया गया है।

Namespace URI से NodeId बनाने का flowयह diagram दिखाता है कि client, namespace URI को server के NamespaceArray में खोजकर index पाता है, और उस index को identifier के साथ जोड़कर NodeId बनाता है।Namespace URIServer का NamespaceArrayIndex (इस example में 2)NodeId ns=2;s=Line1.TemperatureIdentifier Line1.Temperature

चित्र 4: Namespace index को URI से निकालें और identifier के साथ जोड़कर NodeId बनाएँ।

Read और write में value के साथ status और timestamps आते हैं

Variables की value Read और Write services से पढ़ी और लिखी जाती है8। Read में सिर्फ़ value नहीं आती। DataValue नाम के structure में value, status code, source timestamp और server timestamp आते हैं9।

Item मतलब
Value Variable की value। जब status code error बताए तो value को ignore करें, और server उसे null कर देता है
Status code (StatusCode) Server वह value ला पाया और दे पाया या नहीं
SourceTimestamp Data के source ने value पर लगाया हुआ time
ServerTimestamp वह time जब server को value मिली, या पता चला कि value सही है

Status code के ऊपर के 2 bits Good (success), Uncertain (आंशिक success, use के हिसाब से इस्तेमाल लायक न भी हो) और Bad (failure) बताते हैं10। Output का Good [0x00000000] Good है।

मौजूद न रहने वाले Line1.Pressure को पढ़ने पर value की जगह BadNodeIdUnknown [0x80340000] आया। इस library का ReadValueAsync status Bad होने पर exception throw करता है4। Values record करने वाले system में value के साथ status code भी रखें, तो बाद में पहचाना जा सकता है कि कौन सी values Bad के दौरान record हुई थीं।

DataValue के अंदर क्या होता हैयह diagram दिखाता है कि read या notification में आने वाला DataValue चार चीज़ें रखता है: value, status code, source timestamp और server timestamp, और status code Bad हो तो value को ignore किया जाता है।Bad हो तोDataValueValueStatus codeSourceTimestamp (source का time)ServerTimestamp (server का time)Value को ignore करें

चित्र 5: Read का result सिर्फ़ value नहीं, status code और दो timestamps भी रखता है।

Write में Setpoint पर 32.5 लिखा, और result के status code के रूप में Good आया। कौन सा variable writable है, यह server तय करता है। इस simulated server में सिर्फ़ Setpoint writable है। Equipment की settings को बाहर से बदलने देना है या नहीं, यह equipment के safety design से जुड़ा मामला है, इसलिए यह इस article के दायरे में नहीं है।

Changes notify करवाना: subscription और MonitoredItem

Value के changes follow करने के लिए client तय interval पर बार-बार Read कर सकता है। OPC UA में इसके अलावा एक mechanism और है, जिसमें value की monitoring server को सौंप दी जाती है और server changes notify करता है। यही subscription और MonitoredItem हैं।

MonitoredItem, monitor किया जाने वाला एक target है, और इसका एक sampling interval होता है। Sampling interval वह सबसे तेज़ interval है जिस पर server source से value sample करता है, और specification इसे “best effort” cycle कहती है11। जब sample, filter की condition पूरी करता है, तब notification बनता है। Filter न दें, तो value या status बदलने पर notification आता है12।

Notification पहले MonitoredItem की queue में जाता है। Queue भर जाने पर पुराने और नए में से किसे discard करना है, यह पहले से तय किया जाता है, और queue size 2 या उससे ज़्यादा हो, तो discard होने का संकेत देने वाला Overflow bit status code में set होता है13।

Subscription कई MonitoredItems को एक साथ रखता है, और हर publishing interval पर अभी तक न भेजे गए notifications client को भेजता है। अगर लगातार कई cycles में भेजने को कोई notification न हो, तो subscription ज़िंदा है यह बताने के लिए keep-alive भेजता है14।

Subscription और MonitoredItem का flowयह diagram दिखाता है कि MonitoredItem sampling interval पर source की value sample करता है, filter से गुज़रे notifications queue में रखता है, subscription उन्हें publishing interval पर एक साथ client को भेजता है, और notification न हो तो keep-alive भेजता है।Sampling intervalPublishing intervalNotification न हो तोSource (equipment की value)MonitoredItemFilter (default: value या status का change)Queue (भर जाए तो Overflow)SubscriptionClientKeep-alive

चित्र 6: MonitoredItem sample करके queue में रखता है, और subscription उन्हें एक साथ client को भेजता है।

ऊपर के code में Temperature और PartCount को 500 milliseconds के sampling interval और 5 के queue size के साथ subscribe किया15। Output में temperature लगभग हर 0.5 second में, और production count लगभग हर 2 second में आ रहा है। पहले दो notifications वे values थीं जो subscription शुरू होते समय हर variable के पास थीं। Production count का 13:40:50.801 वह time है जब subscription शुरू होने से पहले value बदली थी। Notification के time के रूप में source timestamp दिखाया गया है, इसलिए notification मिलने का time नहीं, बल्कि value बदलने का time दिखता है।

बार-बार Read बनाम subscription: कब कौन सा

बार-बार Read करने में interval client की तरफ़ तय होता है, और mechanism सरल है। लेकिन value न बदली हो तब भी हर बार request और response आते-जाते हैं, और interval से छोटे changes छूट जाते हैं। Subscription में server sample करके सिर्फ़ changes भेजता है, इसलिए कम बदलने वाली values के लिए communication ज़्यादा नहीं बढ़ता। फिर भी subscription में भी sampling interval से छोटे changes notify न हों, ऐसा हो सकता है। Specification तय interval से तेज़ sampling की इजाज़त देती है, लेकिन उसे ज़रूरी नहीं बनाती11।

बार-बार Read और subscription में फ़र्कयह diagram दिखाता है कि बार-बार Read करने में client interval तय करके हर बार request करता है, subscription में server sampling interval पर sample करके सिर्फ़ changes भेजता है, और दोनों में interval से छोटे changes छूट सकते हैं।Value के changes follow करनाबार-बार Read करनाSubscribe करनाClient interval तय करके हर बार request करता हैServer sample करके सिर्फ़ changes भेजता हैInterval से छोटे changes छूट सकते हैं

चित्र 7: दोनों तरीकों में interval से छोटे changes छूट सकते हैं।

Certificate से connection की अनुमति

OPC UA connection में messages की सुरक्षा का स्तर MessageSecurityMode से चुना जाता है। इसकी values हैं: कोई सुरक्षा नहीं देने वाला None, सिर्फ़ signing करने वाला Sign, और signing के साथ encryption करने वाला SignAndEncrypt16। Signing और encryption के algorithms का combination security policy से तय होता है, और इस article में Basic256Sha256 इस्तेमाल किया गया है।

Signing और encryption के लिए हर application का अपना certificate इस्तेमाल होता है। Client और server एक-दूसरे का certificate check करते हैं, और जिस पर भरोसा नहीं, उससे connection reject कर देते हैं। OPC Foundation की .NET library से बना server default रूप से बिना encryption वाली None policy offer नहीं करता4।

पहला connection BadCertificateUntrusted पर रुक गया

पहली बार चलाने पर client, server के certificate पर भरोसा नहीं करता था, इसलिए connection reject हो गया। Output का एक हिस्सा:

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

यह library reject किए गए certificates को rejected store में save करती है। Administrator उसे वहाँ से trusted store में move करे, तो library उस party पर भरोसा करने लगती है17। इस बार pki/rejected/certs में रखे server के certificate को pki/trusted/certs में move किया, फिर से चलाया, और connect हो गया। Move करने से पहले thumbprint, जो file name में भी होता है, server के administrator के साथ confirm करें4।

Certificate पर भरोसा करने तक का flowयह diagram दिखाता है कि पहले connection में client, server का certificate reject करके rejected store में save करता है, और thumbprint confirm करके उसे trusted store में move करने पर अगले connection में भरोसे के साथ connect होता है।पहला connectionBadCertificateUntrustedCertificate rejected store में saveServer के administrator के साथ thumbprint confirm करेंTrusted store में move करेंअगले connection में भरोसे के साथ connect

चित्र 8: Reject हुए certificate को check करके trusted में move करने पर client उस party पर भरोसा करता है।

भरोसा न किए गए certificates को अपने-आप accept करने वाली AutoAcceptUntrustedCertificates setting भी है। इसका default false है, और library का documentation कहता है कि development environment में यह काम की है, लेकिन production में इसका इस्तेमाल न करें17।

Log का NotAfter=2027-11-01, simulated server के certificate की expiry date है। यह asyncua के function से बना self-signed certificate था, और इसकी expiry बनाने की तारीख से एक साल बाद थी। Equipment के certificates की भी expiry होती है, इसलिए expiry से पहले उन्हें बदलने और दूसरी side से उन पर भरोसा करवाने की procedure operations में तय कर लें। Windows certificate store को कैसे संभालें, यह “Windows Certificate Store practical guide” में है।

User authentication

Certificate से applications एक-दूसरे को verify करते हैं। इसके अलावा session खोलते समय user को दर्शाने वाला token दिया जाता है। Specification में चार types हैं: anonymous, user name और password, X.509 certificate, और बाहर issue किया गया token18। इस बार client anonymous रूप से connect हुआ। Server कौन से tokens accept करता है, यह server के endpoint की जानकारी में होता है19।

Field में data collection के दौरान आने वाली दिक्कतें

यहाँ से आगे, equipment का data collect करने वाले systems में आम तौर पर आने वाली problems, इस बार के experiment और specification के आधार पर बताई गई हैं।

Server बंद रहने के दौरान की values नहीं आतीं

Subscription के बीच में server को रोका, और लगभग 15 second बाद फिर से शुरू किया। इस library का ManagedSession connection टूटने पर अपने-आप reconnect करता है20। Server बंद रहने के दौरान client बार-बार reconnect की कोशिश करता रहा।

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.

Server वापस आने पर notifications भी वापस आ गए। Subscription के output का एक हिस्सा:

  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 तक की एक भी value नहीं आई। Production count 78 से वापस 2 पर आ गया है। ऐसा इसलिए हुआ क्योंकि simulated server को restart करने पर उसने गिनती 0 से फिर शुरू की।

इस example में server ही बंद था, इसलिए उस दौरान की values कहीं भी नहीं बचीं। Reconnect का mechanism connection वापस लाता है, लेकिन बंद रहने के दौरान की values बाद में नहीं भरता।

अगर सिर्फ़ communication टूटा हो और server चलता रहा हो, तो बात अलग है। Specification में Republish service है, जिससे न पहुँचे notification messages, server की retransmission queue से दोबारा भेजवाए जा सकते हैं21। MonitoredItem की queue में भी notifications जमा होते हैं, लेकिन queue size से ज़्यादा वाले discard हो जाते हैं13। इस बार के experiment में यह case test नहीं किया। दोनों cases में, किस समय के दौरान values नहीं आईं यह पता चल सके, इसके लिए disconnect और reconnect के times record में रखें। Serial communication वाले equipment में reconnect और log design को “Serial Communication App Pitfalls” में भी cover किया गया है।

Server रोकने पर recordयह diagram दिखाता है कि subscription के दौरान server बंद होने पर client बार-बार reconnect करता है, server वापस आने पर notifications भी वापस आते हैं, लेकिन बंद रहने के दौरान की values नहीं आतीं, इसलिए disconnect और reconnect के times record में रखे जाते हैं।Subscription चल रहा हैServer बंद होता हैClient बार-बार reconnect करता हैServer वापस आता है और notifications भीबंद रहने के दौरान की values नहीं आतींDisconnect और reconnect के times record करें

चित्र 9: Reconnect से connection लौट आता है, लेकिन server बंद रहने के दौरान की values नहीं आतीं।

कौन सा timestamp record करें

Specification के अनुसार SourceTimestamp वह time है जो data के source ने value पर लगाया, और इसे value बदलने का time दिखाना चाहिए। ServerTimestamp वह time है जब server को value मिली या पता चला कि value सही है9। इस बार का simulated server values खुद बनाता है, इसलिए दोनों times एक जैसे थे।

Equipment में value कब बदली, यह जानना हो तो SourceTimestamp इस्तेमाल करें। लेकिन वह time source की clock से लगता है, इसलिए equipment या server की clock आगे-पीछे हो, तो record भी आगे-पीछे होगा। Collect किए गए data को दूसरे records से मिलाना हो, तो receive करने वाले PC का time भी साथ में रखें, ताकि बाद में अंतर check किया जा सके। Windows side का time sync “Windows Time Synchronization (w32time) and Business Systems” में है।

Good के अलावा status वाली values को सीधे numbers की तरह इस्तेमाल न करें

Status code Bad हो, तो value ignore की जानी चाहिए9। Uncertain हो, तो use के हिसाब से value इस्तेमाल लायक न भी हो10। Graph या aggregation में डालने से पहले status code से values छाँटें, और तय करें कि Good के अलावा values के साथ क्या करना है। Queue भरने पर Overflow bit भी status code के अंदर set होता है13। Equipment का status screen पर कैसे दिखाएँ, यह “Best Practices for Checking and Displaying External Device State” में cover किया गया है।

Firewall में port खोलें

IANA में registered OPC UA port 4840/TCP है3। लेकिन हर server यही number इस्तेमाल नहीं करता। OPC Foundation के .NET samples 62541 जैसे ports इस्तेमाल करते हैं4। Equipment के endpoint URL से port number confirm करें, और उस port पर connection allow करें। Server Windows पर चल रहा हो तो उस Windows Firewall में, और बीच में network equipment हो तो उस equipment पर allow करें। Inbound rules बनाने का तरीका “Windows Firewall और business apps” में है।

Data collection में दिक्कतेंयह diagram equipment के data collection में आने वाली दिक्कतों को दो हिस्सों में दिखाता है: record का content (server बंद रहने के दौरान की values न आना, कौन सा timestamp record करें, Good के अलावा values को कैसे संभालें) और connection की तैयारी (firewall का port, certificate की expiry)।Data collection में दिक्कतेंRecord का contentConnection की तैयारीबंद रहने के दौरान की values नहीं आतींकौन सा timestampGood के अलावा valuesFirewall का portCertificate की expiry

चित्र 10: Connect हो जाने के बाद भी records के gaps, time, status, port और certificate check करें।

Modbus/TCP या vendor के अपने communication के साथ चुनाव

PLC और equipment के साथ communication के लिए OPC UA के अलावा Modbus/TCP, और PLC vendor का अपना communication भी होता है।

Modbus specification data को चार tables में रखती है: read-only 1-bit Discrete Input, read-write 1-bit Coil, read-only 16-bit Input Register, और read-write 16-bit Holding Register22। IANA में Modbus application protocol (mbap) के लिए 502/TCP registered है3।

इन tables में सिर्फ़ bits और 16-bit words होते हैं, इसलिए किस address में कौन सी value किस format में है, यह equipment के documentation से confirm करके client की तरफ़ लिखना पड़ता है। OPC UA में, जैसा ऊपर देखा, server नाम वाले variables address space में expose करता है, और client Browse से उन्हें जान सकता है। Values के साथ status code और timestamp आते हैं, और connection के लिए certificate से अनुमति होती है।

कौन सा इस्तेमाल करें, यह ज़्यादातर इस पर निर्भर करेगा कि equipment क्या देता है। Equipment में OPC UA server हो तो उसे इस्तेमाल करें, और सिर्फ़ Modbus/TCP हो तो address mapping table बनाकर पढ़ें। सिर्फ़ vendor का communication या SDK हो, तो उसके documentation के हिसाब से चलें। USB devices के साथ communication का तरीका कैसे चुनें, यह “How to Work with USB Devices from a Windows App” में है।

Equipment के साथ communication कैसे चुनेंयह diagram दिखाता है कि equipment में OPC UA server हो तो OPC UA से variables browse करके collect करते हैं, सिर्फ़ Modbus/TCP हो तो documentation से address और format confirm करके registers पढ़ते हैं, और सिर्फ़ vendor का communication हो तो उसके documentation के हिसाब से चलते हैं।OPC UA serverसिर्फ़ Modbus/TCPसिर्फ़ vendor का communicationEquipment का दिया communicationक्या उपलब्ध है?Variables browse करके collect करेंDocumentation से address और format confirm करेंVendor के documentation और SDK के हिसाब सेRegisters पढ़कर values में बदलें

चित्र 11: किससे collect करें, यह ज़्यादातर इस पर निर्भर करता है कि equipment क्या देता है।

संबंधित लेख

संदर्भ

  1. OPC Foundation, Classic. OPC Classic का COM/DCOM पर आधारित होना, DA, A&E और HDA specifications, 2008 में OPC UA का publish होना, और इसे नए सिरे से बनाने के कारण। ↩ ↩2

  2. IEC, IEC TR 62541-1:2020 OPC Unified Architecture - Part 1: Overview and concepts. IEC 62541 series का Part 1, जो OPC UA के concepts और overview को cover करता है (बाद के edition से replace हो चुका है)। ↩

  3. IANA, Service Name and Transport Protocol Port Number Registry. 4840/TCP पर opcua-tcp और 502/TCP पर mbap का registration। ↩ ↩2 ↩3

  4. OPC Foundation, UA-.NETStandard 2.0.1: Getting started. 2.0 line का client कैसे लिखें, ReadValueAsync का Bad पर exception throw करना, rejected और trusted stores, server का default रूप से None offer न करना, और samples के port numbers। ↩ ↩2 ↩3 ↩4 ↩5

  5. FreeOpcUa, asyncua (PyPI). Simulated equipment server के लिए इस्तेमाल की गई Python की OPC UA library। ↩

  6. OPC Foundation, OPC 10000-4 v1.05, 5.9.2 Browse. Node के references follow करने वाली service। ↩

  7. OPC Foundation, OPC 10000-3 v1.05, 8.2.2 NamespaceIndex. Services के अंदर namespace URI को number से दर्शाना, और उस number का NamespaceArray में position होना। ↩

  8. OPC Foundation, OPC 10000-4 v1.05, 5.11 Attribute Service Set. Read और Write services। ↩

  9. OPC Foundation, OPC 10000-4 v1.05, 7.11 DataValue. Value, status code, SourceTimestamp और ServerTimestamp की definitions। ↩ ↩2 ↩3

  10. OPC Foundation, OPC 10000-4 v1.05, 7.38.1 StatusCode General. ऊपर के 2 bits से बताए जाने वाले Good, Uncertain और Bad। ↩ ↩2

  11. OPC Foundation, OPC 10000-4 v1.05, 5.13.1.2 Sampling interval. Sampling interval का best effort cycle होना। ↩ ↩2

  12. OPC Foundation, OPC 10000-4 v1.05, 7.22.2 DataChangeFilter. Filter न हो तो value या status बदलने पर notification आना। ↩

  13. OPC Foundation, OPC 10000-4 v1.05, 5.13.1.5 Queue parameters. Queue size, discard का तरीका, और Overflow bit। ↩ ↩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 और queue size। ↩

  16. OPC Foundation, OPC 10000-4 v1.05, 7.20 MessageSecurityMode. None, Sign और SignAndEncrypt का मतलब। ↩

  17. OPC Foundation, UA-.NETStandard 2.0.1: Certificates. Rejected store से trusted store में move करने वाला operation, और production में AutoAcceptUntrustedCertificates का इस्तेमाल न करना। ↩ ↩2

  18. OPC Foundation, OPC 10000-4 v1.05, 7.40 UserIdentityToken parameters. चार types: anonymous, user name, X.509, और issued token। ↩

  19. OPC Foundation, OPC 10000-4 v1.05, 7.14 EndpointDescription. Endpoint जो user tokens accept करता है, उनकी list (userIdentityTokens)। ↩

  20. OPC Foundation, UA-.NETStandard 2.0.1: Sessions, Reconnection, and Subscription Engines. ManagedSession में reconnect का mechanism built-in होना। ↩

  21. OPC Foundation, OPC 10000-4 v1.05, 5.14.6.1 Republish. Subscription की retransmission queue से notification messages दोबारा भेजवाने वाली service। ↩

  22. Modbus-IDA, MODBUS Application Protocol Specification V1.1b (University of Chicago के server पर रखी copy). Section 4.3 का data model (Discrete Input, Coil, Input Register, Holding Register)। ↩

निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।

ये इस विषय से जुड़े topic पृष्ठ हैं। लेख से शुरू करके आप संबंधित सेवाओं और दूसरे लेखों तक जा सकते हैं।

बग जाँच / Long-Run विषय

दोबारा पैदा करने में कठिन खराबियों, संचार रुकने, लंबे समय तक चलने के बाद की खराबियों और failure-path testing को व्यवस्थित करने वाला topic।

यह लेख नीचे दिए गए सेवा पृष्ठों से जुड़ता है। जो प्रवेश-बिंदु आपके सबसे क़रीब हो, वहाँ से देखिए।

तकनीकी परामर्श और डिज़ाइन समीक्षा

OPC UA से collect करें या Modbus/TCP या vendor का communication इस्तेमाल करें, और certificates को कैसे manage करें, यह तय करना हो तो इसे technical consulting और design review के रूप में लिया जा सकता है।

अक्सर पूछे जाने वाले प्रश्न

इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।

OPC UA और OPC Classic (OPC DA) में क्या फ़र्क है?
OPC Classic ऐसी specification है जो Windows के COM/DCOM से data exchange करती है। OPC UA 2008 में publish हुई specification है, जो किसी specific OS पर निर्भर नहीं है और Classic के functions को एक साथ संभालती है। OPC UA clients Windows के बाहर भी चलते हैं, और DCOM की setting की ज़रूरत नहीं पड़ती।
OPC UA से values collect करते समय क्या तय interval पर read करना काफ़ी है?
Values कम हों और interval लंबा हो, तो read करके भी collect किया जा सकता है। Values के changes follow करने हों, तो subscription से sampling server को सौंपकर changes notify करवाने का तरीका भी है। दोनों में, value के साथ आने वाला status code और timestamp भी record करें।
Connect करने पर BadCertificateUntrusted क्यों आता है?
क्योंकि client अभी तक server के certificate पर भरोसा नहीं करता। OPC Foundation की .NET library reject किए गए certificates को rejected store में save करती है। Certificate का thumbprint server के administrator के साथ confirm करके उसे trusted store में move करें। Certificates को अपने-आप accept करने वाली setting सिर्फ़ development environment तक रखें।
OPC UA का port number क्या है?
IANA में 4840/TCP, opcua-tcp के नाम से registered है। लेकिन असली servers कभी-कभी दूसरा port इस्तेमाल करते हैं, इसलिए equipment की settings में confirm करें। Server Windows पर चल रहा हो तो Windows Firewall में, और बीच में network equipment हो तो उस equipment पर, उस port के traffic को allow करना होगा।

लेखक की प्रोफ़ाइल

लेख के लेखक का परिचय पृष्ठ।

Go Komura

KomuraSoft LLC के प्रतिनिधि

Windows सॉफ़्टवेयर विकास, तकनीकी परामर्श और बग जाँच पर केंद्रित; जिन परियोजनाओं में मौजूदा assets बचे हैं, उनमें और जिन खराबियों का कारण आसानी से नहीं दिखता, उनकी जाँच में हमारी विशेष ताकत है।

सार्वजनिक लिंक

ब्लॉग पर लौटें