From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: =?UTF-8?Q?Bj=c3=b6rn_Lundin?= Newsgroups: comp.lang.ada Subject: Re: Simple Components 4.12 with MQTT implementation released Date: Thu, 14 Apr 2016 18:19:32 +0200 Organization: A noiseless patient Spider Message-ID: References: <6d3b7ac5-8fc6-406c-8aac-947d25a78249@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Date: Thu, 14 Apr 2016 16:16:31 -0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="6a09ccc49493ecf301ef65af9aa456c7"; logging-data="30824"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/w2l8pJqoMIlDtt8Tk0h78" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.7.0 In-Reply-To: <6d3b7ac5-8fc6-406c-8aac-947d25a78249@googlegroups.com> Cancel-Lock: sha1:8yz4Ln4zC5D2GT2BK8D10DnXkho= Xref: news.eternal-september.org comp.lang.ada:30106 Date: 2016-04-14T18:19:32+02:00 List-Id: 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