Differences
This shows you the differences between two versions of the page.
hellocore [2016/04/26 14:35] mroriz |
hellocore [2017/07/21 03:08] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== HelloCore ====== | ||
- | {{ : | ||
- | This tutorial will guide you through the basic concepts and programming involved in the communication between a mobile node (MN) and a stationary node within the ContextNet SDDL core network [[architecture|]]. This stationary node of the SDDL core will play the role of a server processing node, capable of processing application messages from the mobile node (MN) according to some application specific logic, and sending messages back to the MN. Hence, this tutorial will cover both paths of the communication, | ||
- | Our sample application is composed of two components: a mobile client node and a stationary node, as illustrated in the figure on the right. The MN creates a '' | ||
- | |||
- | The tutorial first shows the code of the mobile client application, | ||
- | |||
- | <WRAP tip> | ||
- | You do not need to copy the source code snippets shown in this tutorial. At the end of each section there is a link to download the entire node source code. | ||
- | </ | ||
- | |||
- | ===== MobileClient ===== | ||
- | To create our mobile client application, | ||
- | |||
- | In SDDL, nodes that are outside the core (either mobile or stationary) interact directly with the Gateway rather than the processing nodes, since it uses a different protocol ([[ClientLib]] and [[MRUDP]]) than the core ([[wp> | ||
- | |||
- | <code java> | ||
- | public class HelloCoreClient { | ||
- | private static String | ||
- | private static int | ||
- | } | ||
- | </ | ||
- | |||
- | After that, we specify our main method. It set ups a debugging information and call the class constructor. The logger shows SDDL debug information; | ||
- | |||
- | <code java> | ||
- | public class HelloCoreClient { | ||
- | private static String | ||
- | private static int gatewayPort = 5500; | ||
- | private MrUdpNodeConnection connection; | ||
- | |||
- | public static void main(String[] args) { | ||
- | Logger.getLogger("" | ||
- | new HelloCoreClient(); | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | We will make the connection with the gateway in our constructor. The client connection is very straightforward; | ||
- | |||
- | <code java> | ||
- | public class HelloCoreClient { | ||
- | // ... | ||
- | | ||
- | public HelloCoreClient() { | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | try { | ||
- | connection = new MrUdpNodeConnection(); | ||
- | connection.addNodeConnectionListener(this); | ||
- | connection.connect(address); | ||
- | } catch (IOException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | We added our object as a '' | ||
- | |||
- | <code java> | ||
- | public class HelloCoreClient implements NodeConnectionListener { | ||
- | // ... | ||
- | | ||
- | @Override | ||
- | public void connected(NodeConnection remoteCon) { | ||
- | ApplicationMessage message = new ApplicationMessage(); | ||
- | String serializableContent = "Hello World"; | ||
- | message.setContentObject(serializableContent); | ||
- | |||
- | try { | ||
- | connection.sendMessage(message); | ||
- | } catch (IOException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | Note that, the connect method receives a '' | ||
- | |||
- | Finally, we need to implement our logic for receiving the messages of the processing nodes. The connection will trigger the '' | ||
- | |||
- | <file java HelloCoreClient.java> | ||
- | package br.pucrio.inf.lac.helloworld; | ||
- | |||
- | import java.io.IOException; | ||
- | import java.net.InetSocketAddress; | ||
- | import java.net.SocketAddress; | ||
- | import java.util.List; | ||
- | import java.util.logging.Level; | ||
- | import java.util.logging.Logger; | ||
- | |||
- | import lac.cnclib.net.NodeConnection; | ||
- | import lac.cnclib.net.NodeConnectionListener; | ||
- | import lac.cnclib.net.mrudp.MrUdpNodeConnection; | ||
- | import lac.cnclib.sddl.message.ApplicationMessage; | ||
- | import lac.cnclib.sddl.message.Message; | ||
- | |||
- | public class HelloCoreClient implements NodeConnectionListener { | ||
- | |||
- | private static String gatewayIP | ||
- | private static int gatewayPort = 5500; | ||
- | private MrUdpNodeConnection connection; | ||
- | |||
- | public static void main(String[] args) { | ||
- | Logger.getLogger("" | ||
- | new HelloCoreClient(); | ||
- | } | ||
- | |||
- | public HelloCoreClient() { | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | try { | ||
- | connection = new MrUdpNodeConnection(); | ||
- | connection.connect(address); | ||
- | connection.addNodeConnectionListener(this); | ||
- | } catch (IOException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | |||
- | @Override | ||
- | public void connected(NodeConnection remoteCon) { | ||
- | ApplicationMessage message = new ApplicationMessage(); | ||
- | String serializableContent = "Hello World"; | ||
- | message.setContentObject(serializableContent); | ||
- | |||
- | try { | ||
- | connection.sendMessage(message); | ||
- | } catch (IOException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | |||
- | @Override | ||
- | public void newMessageReceived(NodeConnection remoteCon, Message message) { | ||
- | System.out.println(message.getContentObject()); | ||
- | } | ||
- | | ||
- | // other methods | ||
- | |||
- | @Override | ||
- | public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, | ||
- | |||
- | @Override | ||
- | public void disconnected(NodeConnection remoteCon) {} | ||
- | |||
- | @Override | ||
- | public void unsentMessages(NodeConnection remoteCon, List< | ||
- | |||
- | @Override | ||
- | public void internalException(NodeConnection remoteCon, Exception e) {} | ||
- | } | ||
- | </ | ||
- | ==== Processing Node ==== | ||
- | The core nodes establishes premises and protocols that are not suitable for mobile applications. To expand this processing power to mobile nodes, we added the concept of gateways that use our lightweight protocol to communicate with mobile nodes and translate their message to core messages. Developers can instantiate nodes to process the mobile nodes message. | ||
- | |||
- | To create our processing node application, | ||
- | |||
- | The processing node uses the DDS protocol to communicate in the core. Thus, it needs to create readers and writers to manipulate data in the core. In addition, it needs to formally join the other core nodes, this is done by recovering an instance of the middleware and creating a participant. After that, it instantiate publishers and subscribers to enable reading and writing data. In our application, | ||
- | |||
- | <code java> | ||
- | public class HelloCoreServer implements UDIDataReaderListener< | ||
- | SddlLayer core; | ||
- | int | ||
- | |||
- | public static void main(String[] args) { | ||
- | Logger.getLogger("" | ||
- | |||
- | new HelloCoreServer(); | ||
- | } | ||
- | |||
- | public HelloCoreServer() { | ||
- | core = UniversalDDSLayerFactory.getInstance(); | ||
- | core.createParticipant(UniversalDDSLayerFactory.CNET_DOMAIN); | ||
- | |||
- | core.createPublisher(); | ||
- | core.createSubscriber(); | ||
- | |||
- | Object receiveMessageTopic = core.createTopic(Message.class, | ||
- | core.createDataReader(this, | ||
- | |||
- | Object toMobileNodeTopic = core.createTopic(PrivateMessage.class, | ||
- | core.createDataWriter(toMobileNodeTopic); | ||
- | |||
- | counter = 0; | ||
- | synchronized (this) { | ||
- | try { | ||
- | this.wait(); | ||
- | } catch (InterruptedException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | To receive the nodes message our processing node need to implement '' | ||
- | |||
- | Our processing node executes a simple logic of returning the number of message received. Therefore, we increment our message counter and create a private message to communicate with the mobile node that sent the message. In the private message, we specify a set of metadata to identify the mobile node, including its node ID and gateway ID that the node is connected. We create an application message that includes this counter and set as the content of our private message. Finally, we send the message to the core to redirect to the mobile node by writing in the '' | ||
- | |||
- | <file java HelloCoreServer.java> | ||
- | package br.pucrio.inf.lac.helloworld; | ||
- | |||
- | import java.util.logging.Level; | ||
- | import java.util.logging.Logger; | ||
- | |||
- | import lac.cnclib.sddl.message.ApplicationMessage; | ||
- | import lac.cnclib.sddl.serialization.Serialization; | ||
- | import lac.cnet.sddl.objects.ApplicationObject; | ||
- | import lac.cnet.sddl.objects.Message; | ||
- | import lac.cnet.sddl.objects.PrivateMessage; | ||
- | import lac.cnet.sddl.udi.core.SddlLayer; | ||
- | import lac.cnet.sddl.udi.core.UniversalDDSLayerFactory; | ||
- | import lac.cnet.sddl.udi.core.listener.UDIDataReaderListener; | ||
- | |||
- | public class HelloCoreServer implements UDIDataReaderListener< | ||
- | SddlLayer | ||
- | int counter; | ||
- | |||
- | public static void main(String[] args) { | ||
- | Logger.getLogger("" | ||
- | |||
- | new HelloCoreServer(); | ||
- | } | ||
- | |||
- | public HelloCoreServer() { | ||
- | core = UniversalDDSLayerFactory.getInstance(); | ||
- | core.createParticipant(UniversalDDSLayerFactory.CNET_DOMAIN); | ||
- | |||
- | core.createPublisher(); | ||
- | core.createSubscriber(); | ||
- | |||
- | Object receiveMessageTopic = core.createTopic(Message.class, | ||
- | core.createDataReader(this, | ||
- | |||
- | Object toMobileNodeTopic = core.createTopic(PrivateMessage.class, | ||
- | core.createDataWriter(toMobileNodeTopic); | ||
- | |||
- | counter = 0; | ||
- | synchronized (this) { | ||
- | try { | ||
- | this.wait(); | ||
- | } catch (InterruptedException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | @Override | ||
- | public void onNewData(ApplicationObject topicSample) { | ||
- | Message message = (Message) topicSample; | ||
- | System.out.println(Serialization.fromJavaByteStream(message.getContent())); | ||
- | |||
- | PrivateMessage privateMessage = new PrivateMessage(); | ||
- | privateMessage.setGatewayId(message.getGatewayId()); | ||
- | privateMessage.setNodeId(message.getSenderId()); | ||
- | |||
- | synchronized (core) { | ||
- | counter++; | ||
- | } | ||
- | | ||
- | ApplicationMessage appMsg = new ApplicationMessage(); | ||
- | appMsg.setContentObject(counter); | ||
- | privateMessage.setMessage(Serialization.toProtocolMessage(appMsg)); | ||
- | |||
- | core.writeTopic(PrivateMessage.class.getSimpleName(), | ||
- | } | ||
- | } | ||
- | </ | ||
- | ===== Execution ===== | ||
- | To execute our application, | ||
- | |||
- | $ gateway 127.0.0.1 5500 OpenSplice | ||
- | |||
- | After that, we instantiate our processing node. To do that, run the '' |