Webportal v1

embedded apps

Application - Quickstart

Building an Application for WebPortal is made easy using web technologies, indeed Apps runs in an iframe in the embedded browser!

  • πŸ‘¨πŸ½β€πŸ’» Build user interface using HTML, CSS and JS.
  • πŸš— Access vehicle APIs.
  • 🌏 MQTT is available as message queuing service.

Head Unit version: remember that they are 2 different version of the vehicle head unit, they are not providing the same vehicle APIs. However this tutorial explains how to build hybrid Apps.

  • NAC were produced between 2017 and 2021, supports ES5 & CSS2.
  • IVI are produced since mid-2021, supports ES6 & CSS3.

Don’t work alone! #

You will need to contact Stellantis Team in order to develop and deploy your Apps on WebPortal, so you should start by doing so! App need to be validated before publication. The team will be able to help you with questions you might have ;)

App Structure & Package #

This tutorial will guide you through the creation of your Application. You can also download this demo App as an example.

This is the file structure your application should use:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
app_<appId>-v<X.Y.Z>_<YYYYMMDD>.md5
app_<appId>-vX.Y.Z_YYYYMMDD.tar.gz
β”‚
└───web/
    └───apps/
    β”‚   └───<appId>/
    β”‚       β”‚   info.json
    β”‚       β”‚   index.html (webportal is a single page app)
    β”‚       β”‚   main.js
    β”‚       β”‚   main.css
    β”‚       β”‚   
    β”‚       └───js/
    β”‚       β”‚      other.js
    β”‚       β”‚
    β”‚       └───css/
    β”‚       β”‚      other.css
    β”‚       β”‚
    β”‚       └───icons/
    β”‚       β”‚      icon-<brand>-100x100.png  (v1 SD screens)
    β”‚       β”‚      icon-<brand>-136x136.png  (v1 HD screens)
    β”‚       β”‚      icon-ds-160x160.png       (v2 DS only)
    β”‚       β”‚      icon-citroen-190x190.png  (v2 CitroΓ«n only)
    β”‚       β”‚      icon-<brand>-128x128.png  (v2 all other brands)
    β”‚       β”‚
    β”‚       └───img/
    β”‚              asset.png
    β”‚
    └───media/
        └───<appId>/
               audio.mp3
               art.jpg

In order to deliver an App, please submit the following package to Stellantis for us to check its behavior before actually deploying it, see App validation. The file structure should follow these requirements:

  • package: The files must be sent in a TAR archive compressed via GZIP, check out the naming section.
  • md5: The .md5 file is required in order to perform an integrity check, see md5 file requirements
  • info.json: application manifest.
  • index.html: file must be present at the root of the project and is the starting point of the application, webportal application are single page app!
  • css: css main file should be located at the root of the project, other css files are located in the css folder. In WebPortal v1 CSS2 is supported, in WebPortal v2 CSS3 is supported.
  • javascript js main file should be located at the root of the project, other javascript files are located in the js folder. In WebPortal v1 ES5 is supported, in WebPortal v2 ES6 is supported.
  • icons: they must be present in the different screen sizes, check out the manifest.
  • img: folder for image files, if your App is storing a lot of offline data, you should use the media folder.
  • media: this folder is required only for App storing a large quantity of static media files, otherwise, media can be stored in web/apps/<appId>.
  • adding folders: the previous file structure cannot be modified but it is possible to add folders if necessary.

App loading: Optimize your code and consider minification, heavy App means long downloading time.

App manifest

The Application package should contain a manifest info.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "artifactId": "<appid>",
  "name": "<appname (optional)>",
  "description": "<appdescription (optional)>",
  "version": "X.Y.Z",
  "buildDate": "YYYY-MM-DD HH:mm",
  "icons": {
    /* Brand specific icon (optionnal)
     "<brand-code>": {
       "100": "icon/icon-<brand>-100x100.png", 
       "136": "icon/icon-<brand>-136x136.png", 
       "160": "icon/icon-<brand>-160x160.png", 
       "190": "icon/icon-<brand>-190x190.png", 
       "128": "icon/icon-<brand>-128x128.png", 
    }, */
    // Default icon
    "*": {
      "100": "icon/icon-100x100.png", // (v1 SD screens)
      "136": "icon/icon-136x136.png", // (v1 HD screens)
      "160": "icon/icon-160x160.png", // (v2 DS only)
      "190": "icon/icon-190x190.png", // (v2 CitroΓ«n only)
      "128": "icon/icon-128x128.png", // (v2 all other brands)
    },
}

Where <brand-code>:

  • Peugeot: AP
  • Citroen: AC
  • DS: DS
  • Opel: OP
  • Vauxhall: VX

Naming and md5 file

  • File name:
    • package filename: app_<appId>-v<X.Y.Z>_<YYYYMMDD>.tar.gz
    • integrity filename: app_<appId>-v<X.Y.Z>_<YYYYMMDD>.md5
  • File content:
    • must be in the following format:
      <MD5_hash_lowercase> app_<appId>-v<X.Y.Z>_<YYYYMMDD>.tar.gz
    • must be newline terminated: \n
Example

For a package:

  • in version 1.2.6,
  • released on the 17th January 2022,
  • with appId is demoApp

Package name will be: app_demoApp_v1.2.6_20220117.tar.gz, and MD5 file content could be:

1
2
098f6bcd4621d373cade4e832627b4f6 app_demoApp_v1.2.6_20220117.tar.gz

HTML (index.html) #

The HTML part of your App is located in the index.html file.

Webportal Apps being Single Page Application, this file is the only html file in the project, you should not use hyperlinks to browse another html file in your App. In order to make the content of your App dynamic, use javascript.

jQuery v1.10.0 library is used for webportal purpose and available offline for App development.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
    <meta charset="UTF-8">
    <head>
      <!-- STYLES -->
      <link rel="stylesheet" type="text/css" href="css/main.css">
      <!-- SCRIPTS -->
      <script type="text/javascript" src="/shared/libs/jquery/1.10.0/jquery.js"></script>
      <script type="text/javascript" src="js/main.js"></script>
    </head>
    <body>
      <div id="my-app">
          Hello World!
      </div>
    </body>
</html>

CSS (main.css) #

CSS file should manage your App style. Using media query it’s possible to target a specific head unit platform.

CSS Version: Webportal v1 supports CSS2 which does not include features like flex box. WebPortal v2 supports CSS3 but you might want to stick to CSS2 if you are building a hybrid Application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* All devices */
#my-app {
    color: blue;
}

/* Only for Webportal v1 SD*/
@media(max-width:1000px){
}

/* Only for Webportal v1 HD*/
@media(min-width:1000px) and (max-width:1500px){
}

/* Only for Webportal v2*/
@media(min-width:1500px){
}

JavaScript (main.js) #

Here is the minimum JavaScript code for your application to function properly.

JS Version: Webportal v1 only supports ES5, WebPortal v2 supports ES6. Check-out demo app for an example of hybrid application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// You should execute javascript only when the DOM is ready
document.addEventListener("DOMContentLoaded", function(event) {

  // Mandatory: Inform the infotainment
  // system that your App is ready
  window.parent.postMessage({
    'type' : 'WebPortal.onApplicationLoaded'
  }, '*');

  // Example of vehicle API:
  // display vehicle VIN
  var myAppElement = document.getElementById("my-app");
  myAppElement.textContent = "Vehicle VIN: " + Car.GetVINCode();
  
  
});

Vehicle APIs #

As seen in the JavaScript section you can interact with the vehicle using webportal. They are different type of vehicle APIs:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* Method: request data */
var CarAutonomy = Car.GetAutonomy();
/* Method: interact with the vehicle */
Navigation.LaunchGuidance("home", 48.866669, 2.33333);

/* Event: subscribe to events */
Media.Audio.addEventListener("audioAvailable", function(){
  alert("An audio source is connected.");
});

/* Inform the infotainment system when your app is */
/* loaded (this API is the only one using postmessage) */
window.parent.postMessage({'type':'WebPortal.onApplicationLoaded'}, '*');