comp.lang.ada
 help / color / mirror / Atom feed
From: "Björn Lundin" <b.f.lundin@gmail.com>
Subject: Re: Simple Components 4.12 with MQTT implementation released
Date: Thu, 14 Apr 2016 18:19:32 +0200
Date: 2016-04-14T18:19:32+02:00	[thread overview]
Message-ID: <neofov$u38$1@dont-email.me> (raw)
In-Reply-To: <6d3b7ac5-8fc6-406c-8aac-947d25a78249@googlegroups.com>

On 2016-04-14 15:01, slos wrote:
> Anyone for OPC ? ;-)
> http://open62541.org/

Via David's gnatcom, you have most of it.
Use it on opcda.dll, and it will create lots of files.
if the prefix id opcda, you'll get
....
opcda-opcitems_interface.adb
opcda-opcitems_interface.ads
opcda-opcitems_object.adb
opcda-opcitems_object.ads
opcda-opcitem_interface.adb
opcda-opcitem_interface.ads
opcda-opcitem_object.adb
opcda-opcitem_object.ads
opcda.ads
...


you then need an application to use the files.
com is no fun to use, but it looks like this
first
 - connect
 - definitions
 - subscribe
 - write
 - read
 - catch events.
there are more events, but group is the most important one




* connect to a server :
      Server                 : aliased IOPCAutoServer_Type;
        Create (This => Server, From => OPCDA.CLSID_OPCServer);
        Connect(This => Server,
                ProgID => Gnatcom.Bstr.
                   To_Bstr("some registered name for a server"));

You then need a group collection
      Group_Collection       : IOPCGroups_Type;
      P_Group_Collection     : Pointer_To_IOPCGroups;


      --group collection
        P_Group_Collection := Get_OPCGroups(This => Server);
        Attach(This => Group_Collection, Pointer => P_Group_Collection);
        Put_DefaultGroupIsActive(This    => Group_Collection,
                                 DefaultGroupIsActive =>
              GNATCOM.Types.VARIANT_BOOL_TRUE);

        Put_DefaultGroupDeadband(This  => Group_Collection,
                                 DefaultGroupDeadband => 0.0);

then you need a group:
      Group                  : IOPCGroup_Type;
      P_Group                : Pointer_To_IOPCGroup;


        P_Group := Add(This => Group_Collection,
                       Name => Gnatcom.Variant.
                  To_Variant("A predefined group"));
        Attach(This => Group, Pointer => P_Group);
        Put_IsSubscribed(This         => Group,
                         IsSubscribed =>
                GNATCOM.Types.VARIANT_BOOL_TRUE);
        Put_UpdateRate(This       => Group,
                       UpdateRate => 0);
        Put_DeadBand(This     => Group,
                     DeadBand => 0.0);


and the group has an item collection

   Item_Collection : OPCItems_Type;
   P_Item_Collection : Pointer_To_OPCItems;


        P_Item_Collection := Get_OPCItems(This => Group);
        Attach(This => Item_Collection, Pointer => P_Item_Collection);
        Put_DefaultIsActive(This            => Item_Collection,
                            DefaultIsActive =>
                    GNATCOM.Types.VARIANT_BOOL_TRUE);


You also need to setup a handler for incoming updates
in a group event

  Group_Event_Object : aliased Opc.Events.Group.Group_Event_Type;
  Group_Event : GNATCOM.Create.COM_Interface.
                  Pointer_To_COM_Interface_Type ;
  Group_Events_Connection_Point : GNATCOM.Events.IConnectionPoint_Type;


        Group_Event :=
OPCDA.DIOPCGroupEvent_Events.Create(Group_Event_Object'Unchecked_Access);

        OPCDA.DIOPCGroupEvent_Events.
              Set_Events(This            =>
                              Group_Events_Connection_Point,
                         For_Object      => Group,
                         Event_Interface => Group_Event);
        Put_ClientName(This       => Server,
                       ClientName =>
           GNATCOM.BSTR.To_BSTR("A client name")));


Now, you need to subscribe to som signals:


      P_Item := AddItem(This         => Item_Collection,
                        ItemId       =>
                  Gnatcom.Bstr.To_Bstr("a signal name"),
                        ClientHandle => C.Long(C_H));
      Attach(This => Item, Pointer => P_Item);
      Put_RequestedDataType(This => Item,
                      RequestedDataType => The_Type);



where the type is one of allowed type, eg
VT_BOOL,VT_UI2,VT_I4. for arrys add VT_ARRAY like
VT_UI2 + VT_ARRAY

take care of the C_H, the client handle.
Update eventes will refer to this value



To write a value:


 declare
   Local_Item : OPCItem_Type;
 begin
   Local_P_Item := GetOPCItem(This         => Item_Collection,
                     ServerHandle => Server_Handle);
       --  Returns an OPCItem specified by server handle
   Attach(This => An_Item, Pointer => Local_P_Item);
   Write(This => Local_Item, Value => Value);
   Free(Local_Item);
end;



to explicitly read a value:


procedure Read(Server_Handle : Interfaces.C.Long) is
      use GNATCOM.Types;
      Quality       : aliased  GNATCOM.Types.Variant;
      Value         : aliased  GNATCOM.Types.Variant;
      TimeStamp     : aliased  GNATCOM.Types.Variant;

    begin
      Gnatcom.Variant.Initialize(Value);
      Gnatcom.Variant.Initialize(Quality);
      Gnatcom.Variant.Initialize(TimeStamp);
 	
      declare
        Local_Item : OPCItem_Type;
      begin
        Local_Item := GetOPCItem(This => Item_Collection,
                                 ServerHandle => Server_Handle);
        Read(This => Local_Item,
           Source => OPCDA.OPCDevice,
           Value => Value'Unchecked_Access,
           Quality => Quality'Unchecked_Access,
           TimeStamp => Timestamp'Unchecked_Access);
        Free(Local_Item);
      end;

      Gnatcom.Variant.Clear(Quality);
      Gnatcom.Variant.Clear(TimeStamp);
      Gnatcom.Variant.Clear(Value);



Disconnect:
     RemoveAll(This => Group_Collection);
     Disconnect(This => Server);
     Finalize(This => Server);
     P_Item := null;
     P_Item_Collection := null;
     P_Group := null;
     P_Group_Collection := null;



for events, you inherit like this


with OPCDA.DIOPCGroupEvent_Events;
with GNATCOM.Types;

package Opc.Events.Group is

   type Group_Event_Type is
     new OPCDA.DIOPCGroupEvent_Events.DIOPCGroupEvent_Event
     with null record;

   procedure DataChange(This          : Group_Event_Type;
                        TransactionID : GNATCOM.Types.VARIANT;
                        NumItems      : GNATCOM.Types.VARIANT;
                        ClientHandles : GNATCOM.Types.VARIANT;
                        ItemValues    : GNATCOM.Types.VARIANT;
                        Qualities     : GNATCOM.Types.VARIANT;
                        TimeStamps    : GNATCOM.Types.VARIANT);

end Opc.Events.Group;


and the body

   procedure DataChange(This          : Group_Event_Type;
                        TransactionID : GNATCOM.Types.VARIANT;
                        NumItems      : GNATCOM.Types.VARIANT;
                        ClientHandles : GNATCOM.Types.VARIANT;
                        ItemValues    : GNATCOM.Types.VARIANT;
                        Qualities     : GNATCOM.Types.VARIANT;
                        TimeStamps    : GNATCOM.Types.VARIANT) is

     use GNATCOM.Types;
     function  Get_Variant is new
            Gnatcom.Safearray.Get_Element(VARIANT);
     function  Get_Integer is new
           Gnatcom.Safearray.Get_Element(Integer);

     Client_Handle,Quality : Integer := Integer'First;
     Value : VARIANT;
     I_Num_Items : Integer  := To_Ada(From => NumItems);
     Handles   : GNATCOM.Types.Pointer_To_SAFEARRAY :=
               To_Pointer_To_SAFEARRAY(ClientHandles);
     Values    : GNATCOM.Types.Pointer_To_SAFEARRAY :=
                   To_Pointer_To_SAFEARRAY(ItemValues);
     The_Qualities : GNATCOM.Types.Pointer_To_SAFEARRAY :=
            To_Pointer_To_SAFEARRAY(Qualities);


-----------------------------------------------------------------------------------


   begin
     --It's important that the words in what is sent back are separated by
     -- one (1) space (' ') and one ONLY! OPC_IO will misinterpret
otherwise!
     -- 'HANDLE server_handle VALUE some_value TYPE some_type'
     Initialize(Value);
     for i in 1 .. I_Num_Items loop
       Quality := Get_Integer(Of_Array => The_Qualities, Index => i);
       Client_Handle := Get_Integer(Of_Array => Handles, Index => i);
       Value := Get_Variant(Of_Array => Values,  Index => i);

        -- do something with value here
       case Value.vt is
         when VT_I2  =>  --Integer_2
         when VT_I4  => --Integer_4
         when VT_BSTR => --Strings
         when VT_ARRAY + VT_I2   |  -- Array of I2
              VT_ARRAY + VT_UI2  |  -- Array of UI2
              VT_ARRAY + VT_I4   =>  -- Array of I4
         when others =>

       end case



     end loop;
     Clear(Value);
   end DataChange;




-- 
--
Björn

  reply	other threads:[~2016-04-14 16:19 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-12 18:48 Simple Components 4.12 with MQTT implementation released Dmitry A. Kazakov
2016-04-14  8:54 ` slos
2016-04-14 10:07   ` Dmitry A. Kazakov
2016-04-14 13:01     ` slos
2016-04-14 16:19       ` Björn Lundin [this message]
2016-04-14 16:49         ` Dmitry A. Kazakov
2016-04-14 20:57           ` Björn Lundin
2016-04-14 21:29           ` slos
2016-04-14 21:20         ` slos
2016-04-15 11:29           ` Björn Lundin
2016-04-15 12:13             ` slos
2016-04-14 16:47       ` Dmitry A. Kazakov
2016-04-14 21:03         ` Björn Lundin
2016-04-14 21:30           ` slos
2016-04-15  8:01             ` Dmitry A. Kazakov
2016-04-15 10:06               ` slos
2016-04-15 11:12                 ` Björn Lundin
2016-04-15 15:05                 ` Dmitry A. Kazakov
2016-04-15 15:17                   ` slos
2016-04-15 15:34                     ` Dmitry A. Kazakov
2016-04-15 16:00                       ` slos
2016-04-15 16:39                         ` Dmitry A. Kazakov
2016-04-15 22:39                           ` slos
2016-04-15 15:47                   ` slos
2016-04-15 16:30                     ` Dmitry A. Kazakov
2016-04-15 22:18                       ` slos
2016-04-16  8:12                         ` Dmitry A. Kazakov
2016-04-16 17:48                           ` slos
2016-04-18 16:33                             ` Dmitry A. Kazakov
2016-04-19 11:51                       ` hanslad
2016-04-19 12:43                         ` Dmitry A. Kazakov
2016-04-19 12:59                           ` high frequency time stamping (Was: Simple Components 4.12 with MQTT implementation released) G.B.
2016-04-19 13:35                             ` Dmitry A. Kazakov
2016-04-20  7:55                               ` Georg Bauhaus
2016-04-20  8:48                                 ` Dmitry A. Kazakov
2016-04-19 13:43                           ` Simple Components 4.12 with MQTT implementation released hanslad
2016-04-19 16:39                             ` Dmitry A. Kazakov
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox