.. highlight:: rst Hello world! ============ Let's get started by sending an OPC UA TCP Hello message to localhost. Setting up your system ---------------------- + We 'll be developping on Debian Squeeze with Python 2.6.6. + We'll be using [Wireshark](http://www.wireshark.org/), with the [OPC ua dissector](http://anonsvn.wireshark.org/viewvc/releases/wireshark-1.6.7/plugins/opcua/) to check our message. + Note: the opc ua dissector is not yet available in Wireshark 1.2.11. This is the version used on Debian squeeze. To solve this we run Wireshark 1.6.7 on Debian Sid inside a chroot. + You should be able to run these snippets with newer versions of python and on other platforms as well. The OPC UA Hello message ------------------------ The hello message is used to negotiate buffer size, message size, and the maximum number of chunks per message to use. It contains the following fields: + MessageType: HEL, from hello + IsFinal: F, from final because the hello message is sent in 1 chunk so it is the final chunk + MessageSize: 32 + the number of characters in the EndpointUrl + ProtocolVersion: 0, because our stack has not been certified it's version is 0 + ReceiverBufferSize: 9000, just an example + SendBufferSize: 9000, just an example + MaxMessageSize: 0, this means unlimited + MaxChunkCount: 0, this means unlimited + EndpointUrl: opc.tcp://opycua:4841, just an example Construct --------- Using Construct we can create a struct, containing these fields.:: :::python from construct import * c = Struct('OPC UA TCP Hello Message', String('MessageType', 3), String('Reserved', 1), ULInt32('MessageSize'), ULInt32('ProtocolVersion'), ULInt32('ReceiveBufferSize'), ULInt32('SendBufferSize'), ULInt32('MaxMessageSize'), ULInt32('MaxChunkCount'), PascalString('EndpointUrl', length_field=ULInt32('length'), encoding='utf8'), ) Snippets -------- We 'll be using 2 snippets. + The first one will act as the OPC ua server. It simply waits and listens on a port. This is necessary because otherwise we cannot send a packet to this port. + The second one will act as the OPC ua client. It will encode the field of the OPC UA hello message as binary data and send it to the listening port. Wireshark will also be running, so we can capture the message. STEP 1: Start listening ----------------------- Snippet:: :::python import socket import sys from construct import * c = Struct('OPC UA TCP Hello Message', String('MessageType', 3), String('Reserved', 1), ULInt32('MessageSize'), ULInt32('ProtocolVersion'), ULInt32('ReceiveBufferSize'), ULInt32('SendBufferSize'), ULInt32('MaxMessageSize'), ULInt32('MaxChunkCount'), PascalString('EndpointUrl', length_field=ULInt32('length'), encoding='utf8'), ) # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('localhost', 4840) sock.bind(server_address) sock.listen(1) while True: print >>sys.stderr, '\nwaiting for a connection' connection, client_address = sock.accept() try: data = connection.recv(53) print >>sys.stderr, 'received "%s"' % data unpacked_data = c.parse(data) print >>sys.stderr, 'unpacked:', unpacked_data finally: connection.close() STEP 2: start Wireshark ----------------------- Listen on the loopback device (lo). STEP 3: Send hello message -------------------------- Snippet:: :::python import socket import sys from construct import * c = Struct('OPC UA TCP Hello Message', String('MessageType', 3), String('Reserved', 1), ULInt32('MessageSize'), ULInt32('ProtocolVersion'), ULInt32('ReceiveBufferSize'), ULInt32('SendBufferSize'), ULInt32('MaxMessageSize'), ULInt32('MaxChunkCount'), PascalString('EndpointUrl', length_field=ULInt32('length'), encoding='utf8'), ) x = Container( MessageType = 'HEL' , Reserved = 'F' , MessageSize = 53 , ProtocolVersion = 0 , ReceiveBufferSize = 9000 , SendBufferSize = 9000 , MaxMessageSize = 0 , MaxChunkCount = 0 , EndpointUrl = 'opc.tcp://opycua:4841', ) packed_data = c.build(x) # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('localhost', 4840) sock.connect(server_address) try: # Send data print >>sys.stderr, 'sending "%s"' % packed_data sock.sendall(packed_data) finally: print >>sys.stderr, 'closing socket' sock.close() Results ------- We hope this little example shows that it is a great idea to implement an OPC ua stack in python. Anyway, here is a screenshot from Wireshark: ![Wireshark - OPC ua hello message](https://sourceforge.net/p/opycua/screenshot/HelloMessage.png) Credit ------ + The socket code in this snippet is based on the [PyMOTW article on the socket module](http://www.doughellmann.com/PyMOTW/socket/tcp.html) by Doug Hellmann. + The OPC ua dissector is created by Gerhard Gappmeier from [ascolab GmbH](http://www.ascolab.com)