The widespread availability of high-end mobile devices such as smart-phones, tablets and phablets, along with the availability of browser enabled devices, has imposed these platforms as one of the main targets for user interfaces. As a result mobile and web applications need now to be easily connected to the rest of the system. This presentation will showcase how the PrismTech Vortex Data Sharing Platform can be effectively and productively used to create connected mobile and web applications, and take you through the steps required to use Vortex in mobile and web applications.
5. Applications can autonomously
and asynchronously read and
write data enjoying spatial and
temporal decoupling
DDS Global Data Space
...
Data
Writer
Data
Writer
Data
Writer
Data
Reader
Data
Reader
Data
Reader
Data
Reader
Data
Writer
TopicA
QoS
TopicB
QoS
TopicC
QoS
TopicD
QoS
Global Data Space
6. Built-in dynamic discovery
isolates applications from
network topology and
connectivity details
DDS Global Data Space
...
Data
Writer
Data
Writer
Data
Writer
Data
Reader
Data
Reader
Data
Reader
Data
Reader
Data
Writer
TopicA
QoS
TopicB
QoS
TopicC
QoS
TopicD
QoS
Dynamic Discovery
7. QoS policies allow to express
temporal and availability
constraints for data
DDS Global Data Space
...
Data
Writer
Data
Writer
Data
Writer
Data
Reader
Data
Reader
Data
Reader
Data
Reader
Data
Writer
TopicA
QoS
TopicB
QoS
TopicC
QoS
TopicD
QoS
QoS - Enabled
8. No single point of failure or
bottleneck
Decentralised
Data Space Data
Writer
Data
Writer
Data
Writer
Data
Reader
Data
Reader
Data
Reader
Data
Writer
TopicA
QoS
TopicB
QoS
TopicC
QoS
TopicD
QoS
TopicD
QoS
TopicD
QoS
TopicA
QoS
9. Connectivity is dynamically
adapted to chose the most
effective way of sharing data
Adaptive Connectivity
Data
Writer
Data
Writer
Data
Writer
Data
Reader
Data
Reader
Data
Reader
Data
Writer
TopicA
QoS
TopicB
QoS
TopicC
QoS
TopicD
QoS
TopicD
QoS
TopicD
QoS
TopicA
QoS
The communication between
the DataWriter and matching
DataReaders can be peer-to-
peer exploiting UDP/IP
(Unicast and Multicast)or
TCP/IP
The communication between
the DataWriter and matching
DataReaders can be
“brokered” but still
exploiting UDP/IP (Unicast
and Multicast)or TCP/IP
10. A domain-wide information’s
class A Topic defined by means
of a <name, type, qos>
Topic
DDS Global Data Space
...
Data
Writer
Data
Writer
Data
Writer
Data
Reader
Data
Reader
Data
Reader
Data
Reader
Data
Writer
TopicA
QoS
TopicB
QoS
TopicC
QoS
TopicD
QoS
Topic
Type
Name
QoS
11. Topic types can be expressed
using different syntaxes,
including IDL and ProtoBuf
Topic Type
struct CarDynamics {
string cid;
long x; long y;
float dx; long dy;
}
#pragma keylist CarDynamics cid
IDL
12. Topic types can be expressed
using different syntaxes,
including IDL and ProtoBuf
Topic Type message CarDynamics {
option (.omg.dds.type) =
{name: "CarDynamics"};
required string cid = 0
[(.omg.dds.member).key = true];
required long x = 1;
required long y = 2;
required float dx = 3;
required long dy = 4;
}
ProtoBuf
13. Topic types can be expressed
using different syntaxes,
including IDL and ProtoBuf
Topic Type
class CarDynamics:
constructor:
(@cid, @x, @y, @dx, @dy) ->
CoffeeScript
14. Topic types can be expressed
using different syntaxes,
including IDL and ProtoBuf
Topic Type
public struct VehicleDynamics {
public string cid { get; set; }
public int x { get; set; }
public int y { get; set; }
public int dx { get; set; }
public int dy { get; set; }
public VehicleDynamics (string cid,
int x, int y, int dx, int dy)
{
this.cid = cid;
this.x = x; this.y = y;
this.dx = dx; this.dy = dy;
}
}
C#
15. Vortex “knows”
about application
data types and
uses this
information
provide type-
safety and
content-based
routing
Content
Awareness struct CarDynamics {
@key
string cid;
long x; long y;
float dx; long dy;
}
cid x y dx dy
GR 33N GO 167 240 45 0
LO 00V IN 65 26 65 0
AN 637 OS 32 853 0 50
AB 123 CD 325 235 80 0
“dx > 50 OR dy > 50”
Type
CarDynamics
cid x y dx dy
LO 00V IN 65 26 65 0
AB 123 CD 325 235 80 0
16. A collection of policies that
control non-functional
properties such as reliability,
persistence, temporal
constraints and priority
QoS
HISTORY
LIFESPAN
DURABILITY
DEADLINE
LATENCY BUDGET
TRANSPORT PRIO
TIME-BASED FILTER
RESOURCE LIMITS
USER DATA
TOPIC DATA
GROUP DATA
OWENERSHIP
OWN. STRENGTH
LIVELINESS
ENTITY FACTORY
DW LIFECYCLE
DR LIFECYCLE
PRESENTATION
RELIABILITY
PARTITION
DEST. ORDER
RxO QoS Local QoS
17. QoS Policies controlling end-to-
end properties follow a Request
vs. Offered
QoS
Domain
Participant
DURABILITY
OWENERSHIP
DEADLINE
LATENCY BUDGET
LIVELINESS
RELIABILITY
DEST. ORDER
Publisher
DataWriter
PARTITION
DataReader
Subscriber
Domain
Participant
offered
QoS
Topic
writes reads
Domain Id
joins joins
produces-in consumes-from
RxO QoS Policies
requested
QoS
28. Vortex device such are used to
share data between different
kinds of applications within a car
Café can be used in Android
based infotainment
Lite in ECU, sensors and
onboard analytics
29. Vortex Fog is used to
transparently (for in car apps)
decouple and control the data
sharing within and across the
car
Vortex Fog also helps defining
security boundaries and
policies
31. Vortex Fog efficiently and
securely deals with cloud
connectivity adapting traffic
flows and protocols
Device-to-Cloud
Communication
Cloud Analytics
Fog Analytics
Fog Analytics
Fog Analytics
32. Vortex Cloud efficiently
and securely makes data
available to any device at
an Internet Scale
Device-to-Cloud
Communication
Cloud Analytics
Fog Analytics
Fog Analytics
Fog Analytics
34. CopyrightPrismTech,2014
• A JavaScript DDS API to provide HTML5/
JavaScript applications with a high-level
communication abstraction
• Vortex Web exploits HTML5 features, such as web-
sockets and web-workers, to provide time and
space efficient Web-App to Cloud communication
Vortex Web
DDS#API JavaScript
Browser#/#Node.js
CoffeeScript
35. CopyrightPrismTech,2014
Client Side (dds.js): JavaScript
CoffeeScript and .NET API for
accessing DDS abstractions
Server Side (vortex-web): A
Router that transparently
bridges data between matching
DDS entities, e.g. Browser-2-
Browser, DDS-2-Browser and
Browser-2-DDS
Vortex Web
TopicA
TopicB
TopicC
TopicD
QoS
QoS
QoS
QoS
Data
Reader
Data
Reader
Data
Writer
Data
Writer
dds.js
dds.js
v-web
v-web
36. CopyrightPrismTech,2014
Vortex-Web takes advantage of HTML5 WebSockets as well as Web Workers
WebSockets are used for both the control as well as the data plane
Web Workers are used to decouple I/O from processing (recall that a JS context is
single-threaded)
Client-Side Architecture / JS
38. CopyrightPrismTech,2014
The .NET client for Vortex-Web takes
advantage of the async / await
support for providing a lightweight,
scalable and efficient client API.
Independent WebSockets are used for
both the control and the data plane
Client-Side Architecture / .NET
40. CopyrightPrismTech,2014
Vortex-Web can be deployed to simply provide access to a “regular” DDS system
or to extend Vortex-Cloud with JavaScript / pure .Net support
In general, you should think of Vortex-Web as an add-on to either a regular or a
Vortex-Cloud DDS system
Vortex-Web takes advantage of DDS to support fault-tolerance and load-
balancing
Vortex Web Deployment
41. CopyrightPrismTech,2014
Multiple instances can be
deployed on a single system to
provide fault-tolerance as well
as to help in partitioning the
load
The switch-over between
instances is dealt-with by the
client library
Traditional System Deployment
TopicA
TopicB
TopicC
TopicD
QoS
QoS
QoS
QoS
Data
Reader
Data
Reader
Data
Writer
Data
Writer
dds.js
dds.js
v-web
v-web
42. CopyrightPrismTech,2014
Multiple instances can be deployed on
the same IaaS platform sa Vortex-
Cloud provide fault-tolerance as well
as to help in partitioning the front-end
load
The switch-over between instances is
dealt-with by the dds.js library
Cloud Based Deployment
VORTEX
Cloud
IaaSserver-side
dds.jsdds.js
48. CopyrightPrismTech,2014
A DataReader can be bound to a user provided function that will handle
incoming data or to a cache
Notice, that as you are in control of how data-readers are bound to cache you
can be very creative
Binding a DataReader
50. CopyrightPrismTech,2014
Binding to a Cache
// Binding
bindCell = dds.bind((s) -> s.x + “-” + s.y)
ccache = new DataCache(historyDepth)
bindCell(ccache, cdr)
// Working with the Cache: Compute number of active cells
activeCells = ccache.map((c) -> if (c.pressure > p0) then 1 else 0).fold(0)
((a, c) -> a + c)
cache = new DataCache(historyDepth)
bind(keyMapper)(dr, cache)
CoffeeScript
Example:
51. CopyrightPrismTech,2014
DataCache Operations
# Writes a data sample into the cache corresponding to the key k
write: (k, data)
# Returns a list representing the content of the cache ordered by key.
read()
# Returns a list representing the last sample for each key
readLast()
# Returns a list representing the content of the cache ordered by key.
# The data is actually removed from the cache.
take()
# Returns a list representing the last sample for each key
# The data is actually removed from the cache.
takeLast()
52. CopyrightPrismTech,2014
DataCache Operations
# Returns a list representing the content of the cache that matches for given predicate.
# The data is actually removed from the cache.
takeWithFilter(p)
# Returns Some(v) if a value associated to the key k exists. Otherwise it returns None
get: (k)
# Returns Some(v) if a value associated to the key k exists. Otherwise it returns f()
getOrElse(k, f)
# Clear the content of the cache.
clear()
53. CopyrightPrismTech,2014
DataCache Operations
# Returns a new DataCache whose content is obtained by applying the function
# f to each element of the cache
map(f)
# Executes the function f on each element of the cache
forEach(f)
# Executes the function f only on the first n samples associated with a key
forEachN(f, n)
# Returns the element of the cache that match the predicate p
filter(p)
# Returns the element of the cache that do not match the predicate p
filterNot(p)
54. CopyrightPrismTech,2014
DataCache Operations
# Folds the content of the data cache using z as “zero” for the folding function f
# For instance, assuming that the operator “+” is defined for the elements of
# the cache, then you could compute the sum of all elements doing:
# c.fold(0)((a, v) -> a + v)
# the product by:
# c.fold(1)((a, v) -> a * v)
# a comma separated string representation of the content:
# c.fold(“”)(a, v) -> a + “, “ + v
fold(z)(f)
# Register a listener l to be notified whenever data which matches a
# predicate p is written into the cache. If no predicate is provided
# then the listeners is always notified upon data insertion.
addListener(l, p)
56. CopyrightPrismTech,2014
Let’s see the steps required
to build a Web Chat that
may look like this
But before let’s play with it
a bit
Web Chat
http://demo.prismtech.com
61. CopyrightPrismTech,2014
Only ~10 lines code for implementing the communication required by a chat
application!
Content filtering could be used to further simplify the application and reduce
number of lines of code, i.e. avoid the check on the origin of the message to
avoid duplicate posts
In Summary
63. CopyrightPrismTech,2014
Very close to the JavaScript/CoffeScript API
Takes advantage of async /await
Pure .Net API without any native dependencies.
.NET API for Vortex Web
64. CopyrightPrismTech,2014
C# implementation of a Chat with a
minimalistic GUI
GUI coded in GTKSharp
The same business logic could be targeted
to Android / iOS using Xamarin Studio
.Net SharpChat
65. CopyrightPrismTech,2014
Topic Types are defined in C#
The Post Type
public class Post {
public string name { get; }
public string msg { get; }
public Post (string name, string msg) {
this.name = name;
this.msg = msg;
}
}
66. CopyrightPrismTech,2014
.Net SharpChat
class MainClass
{
public static void Main (string[] args)
{
var user = args.Length > 0 ? args [0] : “anonymous”;
var uri = args.Length > 1 ? args [0] : ”ws://localhost:9000”;
var vortex = new VortexApp (user, uri);
vortex.Run ();
}
}
67. class VortexApp {
public DataWriter<Post> dw { get; set; }
public DataReader<Post> dr { get; set; }
private MainWindow win;
public string user { get; } public string uri { get; }
public VortexApp(string user, string uri) {
this.user = user;
this.uri = uri;
}
public async Task Init() {
var auth = user + ":nopwd";
var v = new Vortex (0);
await v.Connect (uri, auth);
if (v.IsConnected) {
var tname = "Post";
var post = await v.CreateTopic<Post> (tname);
dr = await v.CreateDataReader<Post> (post);
dw = await v.CreateDataWriter<Post> (post);
} else
Console.WriteLine ("Unable to connect to: " + uri);
}
public void Run () {
Application.Init ();
Init ().Wait ();
win = new MainWindow (user, this.dw);
win.Show ();
dr.OnDataAvailable += (object sender, SampleData<Post> e)
win.addPost(e.Data);
} ;
Application.Run ();
}
}
Listener are lambdas
Readers and Writers are
strongly typed (but can
do projections)
68. using System;
using Gtk;
using vortex.web;
using sharpchat;
public partial class MainWindow: Gtk.Window
{
private DataWriter<Post> dw;
private string user;
[…]
protected void onKeyReleaseEvent (object o, KeyReleaseEventArgs args)
{
var k = args.Event.Key;
if (k == Gdk.Key.Return) {
var rmsg = this.inputText.Buffer.Text;
var msg = rmsg.Remove(rmsg.Length -1);
dw.Write(new Post(this.user, msg));
this.inputText.Buffer.Clear ();
}
}
private void appendToMessageBoard (string user, string msg) {
var text = this.messageBoard.Buffer.Text + " n" + user + " >> " + ms
this.messageBoard.Buffer.Text = text;
}
public void addPost(Post p) {
appendToMessageBoard (p.name, p.msg);
}
}
Async Write
72. Vortex Cafe can be used to develop
android applications in Java
The .Net client for Vortex-Web can
be used to along with Xamain to
develop native applications for
Android , iOS and Windows Phone
The JS client for Vortex-Web can be
used to develop native applications
with Apache Cordova.
74. CopyrightPrismTech,2014
Pure Java version of Vortex targeting JVM
and embedded JVMs
DDSI Protocol Stack optimised for mobility
and Android OS
Only DDS on the market designed and
Engineered for Android
Vortex Café
J2SE
DDSI$$
(Optimised*for*Mobility)*
DDS$API Java Scala JavaScript
76. CopyrightPrismTech,2014
To learn how to write an Android
Application that uses Vortex Café
we’ll develop a very simple Chat
To keep things simple this chat will
have a single “chat room”
DDS Chat for Android
77. CopyrightPrismTech,2014
Our Chat application will have a very simple architecture with simply one
Activity that will take care of:
- Sending Posts into the ChatRoom
- Displaying Posts in the room since when we joined
In terms of information modelling, we’ll have a single topic representing the user
post
Step 1: Architecture
struct Post {
string name;
string msg;
};
#pragma keylist Post name
78. CopyrightPrismTech,2014
Creating DDS entities, such as
DomainParticipants, DataReaders and
DataWriters involves network communication,
such as discovery information
In addition when an a DDS entity is destroyed it
looses its state
As such, tying the life-cycle of DDS entities to
activities should be done with great care
Step 2: Lifecycle Management[1/2]
79. CopyrightPrismTech,2014
In general, it is a better idea to tie the life-cycle of
DDS entities to the Application as opposed to
Activities
In some cases, it may make sense to tie the life-
cycle of DataReaders/DataWriters to that of the
activity that relies on them -- Usually this makes
sense for activities that are “one-off”
Step 2: Lifecycle Management[2/2]
80. CopyrightPrismTech,2014
Applicationpublic class ChatApplication extends Application {
DataReader<Post> dr;
DataWriter <Post> dw;
DomainParticipant dp;
@Override
public void onCreate() {
super.onCreate();
// This should be defined via a resource -- but for a small
// demo that’s OK.
System.setProperty(ServiceEnvironment.IMPLEMENTATION_CLASS_NAME_PROPERTY,
"com.prismtech.cafe.core.ServiceEnvironmentImpl");
ServiceEnvironment env = ServiceEnvironment.createInstance(
ChatApplication.class.getClassLoader());
DomainParticipantFactory dpf =
DomainParticipantFactory.getInstance(env);
dp = dpf.createParticipant(0);
Topic<Post> topic = dp.createTopic("Post",Post.class);
Publisher pub = dp.createPublisher();
Subscriber sub = dp.createSubscriber();
dw = pub.createDataWriter(topic);
dr = sub.createDataReader(topic);
}
83. CopyrightPrismTech,2014
When using Vortex Café you need to grant the proper permissions for
networking:
More Manifest...
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
86. CopyrightPrismTech,2014
Activity
1
2 public class MainActivity extends Activity {
3
4 private static final String TAG = "ChatMainActivity";
5 private final Handler handler = new Handler();
6 private ArrayAdapter<String> chatMessages;
7
8 public class ChatMessageListener extends ChatMessageDataListener {
9 // ...
10 }
11
12 @Override
13 protected void onCreate(Bundle savedInstanceState) {
14 super.onCreate(savedInstanceState);
15 setContentView(R.layout.activity_main);
16 chatMessages = new ArrayAdapter<String>(this, R.layout.messages);
17 chatMessages.add("Welcome to the DDS Chat Room");
18 ListView mview = (ListView) findViewById(R.id.messageList);
19 mview.setAdapter(chatMessages);
20 ChatApplication app = (ChatApplication) getApplication();
21
22 app.reader().setListener(new ChatMessageListener());
23
24 }
25
87. CopyrightPrismTech,2014
Activity
25
26 @Override
27 public boolean onCreateOptionsMenu(Menu menu) {
28 // Inflate the menu; this adds items to the action bar if it is present.
29 getMenuInflater().inflate(R.menu.main, menu);
30 return true;
31 }
89. CopyrightPrismTech,2014
Receiving data is a bit trickier since in Android only the thread that runs an
activity has the right to change the UI
This means, that from a DDS listener it is not possible to change an the UI
directly!
The solution is to use an Android Handler to which we can post Runnable to
be executed by the activity thread
Let’s see how this works...
Receiving Data
90. CopyrightPrismTech,2014
DDS Listener & Android Handler
1 public class ChatMessageListener extends ChatMessageDataListener {
2
3 private DataReader<Post> dr;
4
5 public ChatMessageListener() {
6 ChatApplication app = (ChatApplication) getApplication();
7 dr = app.reader();
8 }
9
91. CopyrightPrismTech,2014
DDS Listener & Android Handler
10 @Override
11 public void onDataAvailable(DataAvailableEvent<Post> dae) {
12 final Iterator<Post> i = dr.read();
13
14 Log.i(TAG, ">>> DataReaderListener.onDataAvailable");
15 if (i.hasNext()) {
16 Runnable dispatcher = new Runnable() {
17 public void run() {
18 while (i.hasNext()) {
19 Sample<Post> s = i.next();
20
21 if (s.getSampleState() == SampleState.NOT_READ) {
22 Post cm = s.getData();
23 chatMessages.add(cm.name + " > " + cm.msg);
24 }
25 }
26 }
27 };
28 handler.post(dispatcher);
29 }
30 }
31 }