Contact: Alain Dechorgnat
The Thingin portal provides to every projects several viewers to embed as an iframe in web applications.
A working example is available at https://gitlab.tech.orange/-/snippets/1115
Availables viewers are:
To see every viewer in action, a test page is available here.
This test page allows you to test viewers with your own dataset or pre defined ones, and to play with the parameters of viewers
To embed a viewer in a web application, you will have to provide informations:
settings of the viewer
what to show, one of:
data for enhancing the graph
and eventually paths to show with Plan2D viewer.
{
"settings": {...},
"graph": {...}, | "request": {...}, | "domainToFollow": "..." | "timeline": []
"highlightGraph": {...},
"paths": {...}
}
Thingin's viewer can do more than showing a "static" graph. We can differenciate 4 principal modes:
simple mode: the viewer receives data of a graph and shows it. In this mode, the viewer can also receive updates of the graph and show them.
request mode: the viewer receives a request at the beginning,and makes the request to Thingin to retrieve the data.
supervision: in this mode, the viewer receives a domain to follow. It will make a first request to show the avatars of the domain, and then start a trigger to receive the domain's updates. It is a simple way to supervise a domain.
timeline mode: the viewer receives an array of snapshots of a graph. It displays a timeline and a player to allow the user to navigate between snapshots.
Settings of the viewer describes the appearence and behaviors of the viewer:
canShowDetails
if true
, the infoWindow will be shown when an avatar is clicked. Default is true
.
noContextMenu
if true
, right clicks won't show any menu. Default is false
.
canFireNodeSelected
if true
, a message of type nodeSelected
will be sent to the parent of the frame. This can be used with canShowDetails=false
if you want to implement your treatment when an avatar is clicked. Default is false
.
nodeSelectedInfo
define the content sent in the nodeSelected message. Values are uuid
for just the uuid of the node or complete
for all the properties of the node. Default is uuid
.
canFireDeadLinkWarning
if true
, a message of type warning
will be sent to the parent of the frame for each link where source or target is not provided in data. Default is false
.
infoWindowTransparency
infoWindow represents the panel opening on the right side of the graph for displaying additional info (object properties, search form, settings form). This panel has a black background and can have a transparency of 0.6 or not. Values are true
or false
. Default value is false
(opaque).
legend
shows or not the graph legend. Values are true
or false
. Default value is false
.
legendDisplay
allows to customize the legend. Available parameters are fontSize
(default 12px), color
(default lightgrey), backgroundColor
(default #00000D80"), borderRadius
(default 10px), border
(thin solid lightgray).
toolbar
shows or not the toolbar. The toolbar is composed of buttons (fulscreen, hide/show legend, search, settings...). Values are true
or false
. Default value is false
.
flatDesign
if true
, the icons will have no relief effect. Default value is false
.
hiddenNodes
,hiddenPolygons
and hiddenLinestrings
allows to hide respectively nodes, polygons and linestrings by class (or label). The format is ["<label_or_iri_class_1>","<label_or_iri_class_2>",...]
or the keyword "_ALL_"
.
niceNameFields
you can provide a list of data_properties to learn to the graph how to add a title to nodes. Data_properties are evaluated from first to last. The first data_property value found for an object will by used as title. If none is found, the _class
property value will be used. This title is also used for tips shown when mouse is over an avatar.
customPalette
you can provide the palette of colors to use for avatars and links. This can be the name of the palette (standard
,vibrant
or pastel
) or your own array of colors in html format (ex: ["aquamarine", "#FF66FF66", "#aaa"]
).
customColors
you can provide a list of avatar's classes and colors to use for avatars. The format is {"<iri_class_1>": "<color_1>", "<iri_class_2>": "<color_2>",...}
. If some avatars have classes with no custom color, they will take a color in the palette.
computedCustomColors
you can provide a list of avatar's classes or labels and computation of colors to use for avatars. The format is {"<iri_class_1>": {<color_computation_1>}, "<iri_class_2>": {<color_computation_2>},...}
.
Computation is foremed as follows:
{
"valueField": "<data_property or label">,
"computedColor": "see bellow"
}
computedColor can be :
* discrete values: {'on':'green', 'off':'red'}
* range values : {'[0,70]':'green', '[70,85]':'darkorange', '[85,100]':'red'}
customAvatarColors
you can provide a list of avatar's uuid and colors to use for avatars. The format is {"<_uuid_node_1>": "<color_1>", "<_uuid_node_2>": "<color_2>",...}
. Custom color of an avatar will replace the color for its class. The color parameter could be a valid css color or %<property>
to take the color in a propety of the avatar.
customClassIcons
you can provide a list of avatar's classes and icons to use for avatars. The format is: [{class: <class_iri>, icon: <icon_url>}, ...]
. <icon_url> is a true URL or a base64 encoded image.
customAvatarIcons
you can provide a list of avatar's uuid and icons to use for avatars. The format is: [{_uuid: <avatar_uuid>, icon: <icon_url>}, ...]
. <icon_url> is a true URL or a base64 encoded image.
classDecorators
you can provide a list of class iris and decorators to use for avatars. The format is: {"<class_iri>": <decorator>, ...}
. You'll find decorators description there.
customStyles
you can provide a list of CSS class to be reused in custom menu descriptions. The format is: {"cs_<class>": "<css_description>", ...}
. Only classes starting with 'cs_' will be used: see there for more information.
customClassMenus
you can provide a list of class iris and custom menus to use for avatars. The format is: {"<class_iri>": <custom_menu>, ...}
. You'll find custom menu description there.
mapTypeControl
enables/disables the Map Type control that lets the user toggle between map types (such as Map and Satellite). The default is true
.
zoomControl
enables/disables the Zoom control. By default, this control is visible.
scaleControl
enables/disables the Scale control that provides a simple map scale. The default value is true
.
userGeoLocation
if true
, add a button in toolbar to locate the user. It needs toolbar=true
. Default is false
.
polygonsBorder
add a border to polygons. Default is true
google_api_key
your google API key. see https://developers.google.com/maps/documentation/javascript/get-api-key.
mapType
the type of map to display using the Google Maps. The default value is terrain. Available values are:
roadmap
: displays the default road map view. This is the default map type.satellite
: displays Google Earth satellite imageshybrid
: displays a mixture of normal and satellite viewsterrain
: displays a physical map based on terrain information.blank
: blank page backgrounddark
: like roadmap but with a dark themestreetViewControl
enables/disables the Pegman control that lets the user activate a Street View panorama. The default value is true
.
rotateControl
enables/disables the appearance of a Rotate control for controlling the orientation of 45° imagery. The default value is true. The control's presence is determined by the presence or absence of 45° imagery for the given map type at the current zoom and location. You cannot make the control appear if no 45° imagery is currently available.
mapType
the type of map to display using the OpenStreetMap. The default value is terrain. Available values are:
roadmap
: displays the default road map view. This is the default map type.satellite
: displays satellite imagesusePictos
:
if true
, it will use icons for avatars. Default is false
.
blueprint
"blueprint": {
"url" : "PROLANN-RDC.svg", // image url
"id": "prolann", // id of svg element in file
"scale": 1.063 - 500/37.85, // pixels/m
"clustering": true,
"clusteringFactor": 1.5,
"positionField": "i40:indoor_location",
"positionAttributes": ["x", "y", "z"],
"indoorLocation":{
"origin": {"x": 198, "y": 248},
"rotation" : -90 // rotation in degrees
},
"ifc" : {
"origin": {"x": 198, "y": 248},
"rotation": 100 // rotation in degrees
}
}
You can provide a plan in svg, jpeg or png format, but it is not mandatory. If you don't have one, leave url
and id
blank, a white background will be used. If you have one, provide its url and for svg, indicate the id of the part of the svg file to be used. For other image formats, id
is left blank.
The scale
parameter represents the scale of the plan in pixel per meter.
The clustering
parameter tells if too closed avatars must be clustered or not. Default is true.
The clusteringFactor
parameter set the strength of clustering. It will be used with marbleRadius
to set the width of a cluster. Default value is 2
.
The positionField
parameter represents the name of the field where to find the avatar's coordinates. The default is http://orange-labs.fr/fog/ont/object-location.owl#locationPayload
.
The positionAttributes
parameter represents the name of the attributes in the position field for avatar's coordinates. The default is ["coordX", "coordY", "coordZ"]
.
To calibrate the indoor location, you must provide the position of the origin on the plan: x is the number of pixels from the left and y from the top.
You can also rotate the plan at screen.
If some avatars have been extracted from a IFC file, they can have calculated projections. In order to show them on the plan, you must provide the position of the IFC point of reference on the plan. Normally, IFC files are oriented Y to North. For a good orientation of projection, you must also provide the rotation to align north on plan
You can force the position of a node in the graph with the value of a field of the avatar (like in Plan2D visualization). Avatars that don't have this field will be left free.
Two modes are available:
For 2D positions from field, the configuration is
"graph2D": {
"positionType": "XY",
"positionScale": 20000,
"positionOffset": {
"x": 100,
"y": 300
}
"positionField": "i40:graph2DPosition",
"positionAttributes": [
"x",
"y"
],
}
For GPS positions, here is the configuration:
"graph2D": {
"positionType": "GPS",
"positionScale": 10,
"positionOffset": {
"x": -4.02499,
"y": 39.856655
}
"positionField": "http://www.opengis.net/gml/pos",
"positionAttributes": "coordinates",
}
Notice that the positionOffset
field is the GPS coordinates of the center of the screen.
showIfcSpaces
: if set as true
, 3d viewer will show ifcSpaces in 3D. Default is false
.backgroundColor
:#RRGGBB
, #rgb
, #RRGGBBAA
, #rgba
or a web color name. The default value is #545454 (a dark grey). This parameter has no effect on map viewers"settings": {
"infoWindowTransparency": true,
"legend": false,
"toolbar": true,
"niceNameFields": ["", ""],
"backgroundColor": "lightgray",
}
Data for the graph (nodes and links) is the raw result of a Thing'in request with the format application/ziggy-json
and is the value of the graph
parameter.
Here is an exemple of this format with two nodes and a link:
"graph": {
"nodes": [
{
"_ori": "http://orange-labs.fr/fog/ont/datashare.owl#Device-10506",
"ont_datashare_owl_created": "2017-08-02T06:44:18Z",
"_last_updated": 1505229641979,
"_uuid": "17ed4dd9-50e0-436d-92e3-12277da2600e",
"ont_datashare_owl_lastSync": "2017-09-12T15:07:40Z",
"ont_datashare_owl_error": "NONE",
"_classes": ["http://orange-labs.fr/fog/ont/datashare.owl#Lifx"],
"ont_datashare_owl_id": 10506,
},
{
"_ori": "http://orange-labs.fr/fog/ont/datashare.owl#Connector-3606",
"ont_datashare_owl_created": "2017-08-02T06:44:18Z",
"_last_updated": 1505229642278,
"_uuid": "7c4fce52-bfb1-4104-bf31-9d32b720a3c1",
"ont_datashare_owl_error": "NONE",
"_classes": ["http://orange-labs.fr/fog/ont/datashare.owl#Connector"],
"ont_datashare_owl_id": 3606,
"ont_datashare_owl_key": "-",
}
],
"links": [
{
"source": "7c4fce52-bfb1-4104-bf31-9d32b720a3c1",
"target": "17ed4dd9-50e0-436d-92e3-12277da2600e",
"value": "ont_datashare_owl_hasDevice"
}
]
}
If you specify a request
parameter, it will be used to retrieve the data to show in the viewer.
For that, you need to provide 2 other parameters:
thinginToken
: the token provided by Thingin when calling GET /auth,thinginEndpoint
: the url of the Thingin platform you want to use. By example: https://coreapi.thinginthefuture.com,Here is an example or a request and its parameters.
"request" : {
"payload" :
{
"query" : {
"$domain": "http://thingin.orange.com/ifc/Meylan_v3/"
},
"view": {}
},
"options" : {
"size": 1000,
"index": 0
}
}
The viewer will call the api of Thingin POST /avatars/find
with the provided payload and options.
This is a simple way to supervise a domain. 2 parameters are needed:
domainToFollow
: the domain name to supervizedomainToFollowSize
: the initial number of avatars to load before supervizing.If domainToFollowSize
has a non null value (<1000), the viewer will make a first request to show at max domainToFollowSize
avatars of the domain. If not, the viewer will be empty at the beginning.
Then it will start a trigger to receive the domain's updates.
This is a mode that concerns the historization feature of Thingin. The viewer receives an array of snapshot of a graph. It displays a timeline and a player to allow the user to navigate between snapshots.
You must specify a timeline
parameter for this mode:
"timeline": {
"timestampDisplay": {
"display": true,
"position": "upperLeft",
"color": "lightgrey",
"backgroundColor": "#00006688"
"dateTimeFormat": "HH:mm:ss"
},
"timelineDisplay": {
"mainColor" : "green",
"compColor" : "white",
"textColor": "#3dcd58",
"backgroundColor": "#000D",
"activeStepColor": "#fff",
"activeStepBorderColor": "darkgrey",
"borderTopColor": "darkgrey"
},
"showTimeline": true,
"proportional": true,
"replayLength": 15 * 1000, // 15s
"autostart": false,
"steps": [
{
"comment": "Step 1",
"timestamp": 1646039901000,
"graph": {}
},
...
]
}
timestampDisplay
allows to show a date/time panel on the screen. display
can show or not the panel (default is true
). position
is the location on the screen, possible values are upperLeft
, upperRight
, bottomLeft
, bottomRight
, default is upperLeft
. color
and backgroundColor
describe the apparence of the panel, default colors are darkOrange
and transparent
. dateTimeFormat
is the transformation of the date to display, default is YYYY-MM-DDTHH:mm:ss.SSSZ
.showTimeline
tells if the timeline should be displayed.proportional
: if true
, events are shown on the timeline by taking in account the timestamp.false
, events are evenly spaced on the tmeline.replayLength
is the total duration to replay all stepsautostart
allows to start automatically the replay.steps
is an array of steps described by a timestamp
and a graph
. comment
is optional and has no effect.The Plan2D viewer can also visualize paths over the background image and under the avatar icons .
You need to provide a parameter paths
(not in settings
but at the same level than graph
) with the folowing structure:
[
{
"id": 1,
"pathColor": "#00FF0088",
"pathWidth": 6,
"pathIsClosed": false,
"pathStyle": "solid",
"bulletShape": "round",
"bulletFillColor": "green",
"bulletTextColor": "white",
"bulletSize": 20,
"points": [
{
"x": 6,
"y": 17,
"text": "Storage"
},
{
"x": 14,
"y": 14,
"text": "Wiring"
},
{
"x": 8,
"y": 2,
"text": "Waiting",
"bulletFillColor": "red",
"bulletSize": 30
}
]
}
]
Notice that you can also display polygons if the field pathIsClosed
is set to true
.
You can configure different parts of the graph like nodes and links with the highlightGraph
parameter:
a node can be:
a link can be hilighted (graph viewers only). In this case, its representing line will be larger and a 'fireball' will follow the link. For exemple, this can be used for showing a path in a graph.
The format of those data is a JSON object, very similar to the previous format. In this case, only _uuid
property is mandatory for nodes and id
for links:
"highlightGraph": {
"nodes" : [
{
"_uuid": "17ed4dd9-50e0-436d-92e3-12277da2600e",
"_highlighted": false,
"_position": {
"x": 50,
"y": 200
}
},
{
"_uuid": "7c4fce52-bfb1-4104-bf31-9d32b720a3c1",
"_highlighted": true,
"_centered": true,
},
...
],
"links" : [
{
"id": "43c1598c-9908-536d-95cf-99de5df34f85"
}
...
]
}
In this exemple the first node will have a fixed position in the graph. Position is relative to the center point of the iframe: in this case, the first node will be placed at 50 pixels to the right of the center and 200 pixels below. This node will not have an underlying glowing effect ("_highlighted": false
). We could have simply omitted the parameter.
The second node will not be centered ("_centered": true
) and have an underlying glowing effect ("_highlighted": true
).
The dialog between the host page and the iframe relies on HTML5 window messaging system
The initialisation follows this workflow:
load
event to the host pageSee code example below.
The iframe can have a context menu to allow to reset the graph.
See code example below.
If using canFireNodeSelected=true
, the iframe will send a message to the host page when the user clicks on an avatar.
The message will contain:
{
"type":"nodeSelected",
"params":{
"_uuid":"527d1620-85a7-4918-9437-32ac7a771f48"
}
}
You'll need to insert an iframe in you application page like this:
<iframe id="myIframe"
title="Visualization"
style="border: none; height:100%; width:100%"
allowfullscreen="true"
allowtransparency="true">
<p>Your browser does not support iframes.</p>
</iframe>
and the following script
let messageNotSent = true;
let graphData = {
"settings": {...},
"graph": {...},
"highlightGraph": {...}
}
let graphDataMessage = JSON.stringify(graphData);
const iframe = document.getElementById('myIframe');
iframe.addEventListener('load',function () {
console.log('load event received');
if (messageNotSent) {
iframe['contentWindow'].postMessage(graphDataMessage, "*");
messageNotSent = false;
}
});
window.addEventListener('message',
function (event) {
console.log('message received: '+event.data);
if (event.data == 'rearm') messageNotSent = true;
else {
if (event.data.type === 'nodeSelected'){
// your code
}
}
},
false);
iframe.src="viewer URL (see bellow)";
Viewers URLs are:
The messaging system between the host page and the viewer allows much more interactions with the visualizations. Take a look at Visualisation framework messaging system for a full description of this system.