For more information, including FAQs and resources, please visit the link below:
RDKM-SSO
Any questions or comments please feel free to contact RDK Support team support@rdkcentral.com . Thank you. ***
This document guides users to perform the below activties on a Raspberry Pi (Rpi) platform as well as an Amlogic Reference platform
Info | ||||
---|---|---|---|---|
| ||||
On this Page:
|
Background Color | ||
---|---|---|
| ||
Before you begin |
Though not mandatory, the below skills will help the user to understand RDK, RDK build, and to try out RDK better :
<work in progress>
Table of Contents |
---|
RDK is an open source code project distributed through industry standard open source licenses e.g. Apache 2.0.
Basic skills needed by a user to use the current documentation
Basic knowledge of Ubundu
Basic Build knowledge
Basic RDK knowledge
Basic knowledge of using a Raspberry Pi boxes (If trying in Raspberry Pi)
Basic knowledge of how to perform flashing and bring up a Raspberry Pi setup
Skills to connect and bring up Reference Board (If trying with Reference Board)
AUI Tab Group |
---|
|
Hardware requirements and setting up the host environment and Downloading Source Code is explained below.
Setting up the Host Environment
|
Requirement | Yocto | |||
---|---|---|---|---|
3. | ||||
1 LTS ( | ||||
Dunfell) | Yocto 3.1 LTS (Dunfell) | |||
Linux PC | Linux | 32/64 bit Ubuntu 16.04 LTS Precise supported distributions and versions are here 64 bit Ubuntu 18.04 LTS Precise supported distributions and versions are here | ||
Free HDD Space | Minimum 100GB Free MemoryMinimum 100GB Free memory space | |||
Oracle Virtual Box | 5.0.40 or higher | - | ||
Wireless Adapter | Brand Name: Tenda ralink & Model Number:W311MI TP-Link Archer T4U AC 1200 | - | USB to Ethernet Switch | To connect with Ethernet Switch & Multiple Clients |
Host Tools version | Git 1.8.3.1 or greater tar 1.24 or greater Python 2.7.3 | Git 1.8.3.1 or greater tar 1.28 or greater Python 3.5.0 or greater |
The instructions provided below are meant to be executed via the command line on an Ubuntu machine
Code Block | ||||
---|---|---|---|---|
| ||||
# essential packages installation
# super user mode is required
# major essential packages
sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib g++-multilib build-essential chrpath socat bison curl
# supportive packages
sudo apt-get install libfile-slurp-perl libncurses-dev autoconf flex doxygen libtool automake libpcre3-dev zlib1g-dev libbz2-dev subversion minicom putty libssl-dev rpm python-pexpect python-svn python-argparse vim tofrodos meld dos2unix cmake uuid-dev ruby transfig libglib2.0-dev xutils-dev lynx-cur gperf autopoint python-dulwich python-dev openjdk-7-jre |
Note : Please note openjdk-7-jre package is not available for Ubuntu-16.04 anymore. Presumably openjdk-8-jre should be used instead.
Code Block | ||||
---|---|---|---|---|
| ||||
# essential packages installation
# super user mode is required
# major essential packages
sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib g++-multilib build-essential chrpath socat bison curl cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm
|
Configure bash as default command interpreter for shell scripts
Code Block | ||
---|---|---|
| ||
sudo dpkg-reconfigure dash |
Select “No”
To choose bash, when the prompt asks if you want to use dash as the default system shell - select “No”
Configure Git
Upgrade your Git version to 1.8.x or higher
On Ubuntu 16.04 LTS, if you are unable to upgrade your git version using apt-get, then follow the below steps in order to upgrade
Code Block | ||
---|---|---|
| ||
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git |
Once git is installed, configure your name and email using the below commands
Code Block |
---|
# review your existing configuration
git config --list --show-origin
# configure user name and email address
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
# configure git cookies. Needed for Gerrit to only contact the LDAP backend once.
git config --global http.cookieFile /tmp/gitcookie.txt
git config --global http.saveCookies true |
Configure repo
In order to use Yocto build system, first you need to make sure that repo is properly installed on the machine:
Code Block | ||
---|---|---|
| ||
# create a bin directory
mkdir ~/bin
export PATH=~/bin:$PATH
# Download the repo tool and ensure that it is executable
curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo |
Trivia : Repo is a repository management tool that is built on top of Git. Its main purpose is to help manage projects that consist of many Git repositories, it can also be used to manage uploads to the CMF Gerrit instance and automate aspects of the development workflow.
Repo does not replace Git, it simply aids management of projects that contain multiple Git repositories into a single local working directory. Git will still be used for local operation such as commits etc.
Repo manages this for you by means of an XML based Manifest file. The Manifest file defines which repositories the project uses and links to appropriate revisions of each git repository, i.e where the upstream repositories reside and where they should be cloned locally. It is the manifest.xml (or default.xml) that determines which Git repositories and revisions repo will manage. This manifest.xml file is hosted in a Git repository along with all the other git repositories.
Credential configuration
Note: it is also recommended to put credentials in .netrc when interacting with the repo.
A sample .netrc file is illustrated below
machine code.rdkcentral.com login <YOUR_USERNAME> password <YOUR_PASSWORD> |
---|
Downloading Source Code
Following commands fetch the source code using repo tool
$ mkdir <Directory-Name> && cd <Directory-Name>
Please use the following repo init command
$ repo init -u https://user@code.rdkcentral.com/r/manifests -m manifest.xml -b <branch_name>
Examples :
repo init -u https://code.rdkcentral.com/r/manifests -m rdkb.xml -b rdkb-20180527
repo init -u https://code.rdkcentral.com/r/manifests -m rdkb.xml -b master
repo init -u https://code.rdkcentral.com/r/manifests -m rdkb.xml -b morty
$ repo sync -j`nproc` --no-clone-bundle
Warning |
---|
|
Building
$ source <setup-environment>
The above step configures and sets up your directory to start an appropriate build.
There are different kinds of builds listed. Please read the options and select the number of the build you need.
1) meta-rdk-bsp-emulator/conf/machine/qemuarmbroadband.conf
2) meta-rdk-bsp-emulator/conf/machine/qemux86broadband.conf
3) meta-rdk-bsp-emulator/conf/machine/qemux86hyb.conf
4) meta-rdk-bsp-emulator/conf/machine/qemux86mc.conf
5) openembedded-core/meta/conf/machine/qemuarm.conf
6) openembedded-core/meta/conf/machine/qemux86-64.conf
7) openembedded-core/meta/conf/machine/qemux86.conf
Next, you need to initiate the build using the following command:
$ bitbake <image-name>
On Successful build, the ROOTFS (in vmdk format) would be available at the following reference location based on the build type :
-$ {HOME}/emulator/build-qemux86broadband/tmp/deploy/images/qemux86broadband/rdk-generic-broadband-image-qemux86broadband-<timestamp>.vmdk
Example :
…/build-qemux86broadband/tmp/deploy/images/qemux86broadband/rdk-generic-broadband-image-qemux86broadband-20160217080610.vmdk
Host Setup
Refer the section Setting up the Host Environment for host setup details
Code Block | ||||
---|---|---|---|---|
| ||||
repo init -u https://code.rdkcentral.com/r/manifests -b dunfell -m rdkv-nosrc.xml
repo sync -j `nproc` --no-clone-bundle --no-tags |
Instruction to build media client image
Code Block | ||||
---|---|---|---|---|
| ||||
MACHINE=raspberrypi-rdk-mc source meta-cmf-raspberrypi/setup-environment
bitbake rdk-generic-mediaclient-wpe-image |
Hybrid Gateway
Instruction to build hybrid gateway image
Code Block | ||||
---|---|---|---|---|
| ||||
MACHINE=raspberrypi-rdk-hybrid source meta-cmf-raspberrypi/setup-environment
bitbake rdk-generic-hybrid-wpe-image |
Instruction to build hybrid gateway image with operator reference application
Code Block | ||||
---|---|---|---|---|
| ||||
MACHINE=raspberrypirdkhybrefapp source meta-cmf-raspberrypi/setup-environment
bitbake rdk-generic-hybrid-refapp-image |
The generated image resides under the directory build-<MACHINE>/tmp/deploy/images/<MACHINE>
of the Yocto workspace
The micro SD card should not have any partition while flashing the image. The complete memory of the card should be free
Code Block | ||
---|---|---|
| ||
# of - output file (the device file for the inserted micro SD card
bzcat <IMAGE_NAME>-<MACHINE>.wic.bz2 | sudo dd of=/dev/sdb bs=4M iflag=fullblock oflag=direct conv=fsync |
Same as RPI-above section and this can combine and can be made one.
All RPi based RDK images with the latest features are from the rdk-next branch
To build RDK images from ipstb_bringup branch, follow the below build procedure
Code Block | ||||
---|---|---|---|---|
| ||||
mkdir workspace
cd workspace
# initialize the manifest with repo tool
repo init -u https://code.rdkcentral.com/r/rdkcmf/manifests -b rdkv-2021q3 -m rdkv-extsrc.xml
repo sync -j `nproc` --no-clone-bundle --no-tags |
Code Block | ||||
---|---|---|---|---|
| ||||
MACHINE=raspberrypi-rdk-ipmc source meta-cmf-raspberrypi/setup-environment
bitbake rdk-generic-ipclient-image |
The image file will be generated under build-<MACHINE>/tmp/deploy/images/<MACHINE>
directory.
eg: dsrava434@dvm-yocto3-docker-dsrava434:~/varsha/build-raspberrypi-rdk-ipmc/tmp/deploy/images/raspberrypi-rdk-ipmc$ pwd
/home/dsrava434/varsha/build-raspberrypi-rdk-ipmc/tmp/deploy/images/raspberrypi-rdk-ipmc
dsrava434@dvm-yocto3-docker-dsrava434:~/varsha/build-raspberrypi-rdk-ipmc/tmp/deploy/images/raspberrypi-rdk-ipmc$ ls -lrt rdk-generic-ip-stb-client_rdk-next_20210913112356.rootfs.wic.bz2
-rw-r--r-- 2 dsrava434 dsrava434 141959535 Sep 13 12:33 rdk-generic-ip-stb-client_rdk-next_20210913112356.rootfs.wic.bz2
dsrava434@dvm-yocto3-docker-dsrava434:~/varsha/build-raspberrypi-rdk-ipmc/tmp/deploy/images/raspberrypi-rdk-ipmc$
Code Block | ||
---|---|---|
| ||
# Insert the micro SD card to the host system and mention the card's device file name
# input file (if) is the image file to flash and the output file (of) is the card's device file name
bzcat <image name> | sudo dd of=/dev/<sd file> bs=4M iflag=fullblock oflag=direct conv=fsync |
root@raspberrypi-rdk-ipmc:~# cat /version.txt imagename:rdk-generic-ip-stb-client_rdk-next_20210902101930 BRANCH=rdk-next YOCTO_VERSION=dunfell VERSION=4.09.02.21 SPIN=0 BUILD_TIME="2021-09-02 10:19:30" Generated on Thu Sep 02 10:19:30 UTC 2021 root@raspberrypi-rdk-ipmc:~# |
---|
eg :- gst-launch-1.0 playbin uri=aamp://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8 video-sink=westerossink
S. No
Issues
Status
Remarks
S. No
Issues
Status
Remarks
As work around, comment out On failure from dsmgr.service.
Path : /lib/systemd/system/dsmgr.service
Comment out " OnFailure=reboot-notifier@%i.service"
Jira Ticket: REFPLTV-1099 - Rebooting observed in RPi3 device in IPSTB image IN PROGRESS
Code Block | ||
---|---|---|
| ||
$ mkdir <RDK_DIR>
$ cd <RDK_DIR>
$ repo init -u https://code.rdkcentral.com/r/collaboration/soc/amlogic/aml-accel-manifests -b rdk-next -m rdk-firebolt-dunfell-ref-sc2-k54-202109.xml
$ repo sync -j4 --no-clone-bundle
or
$ repo init -u https://code.rdkcentral.com/r/collaboration/soc/amlogic/aml-accel-manifests -b rdk-next -m rdk-firebolt-dunfell-ref-sc2-k54-202109.xml --repo-branch=v2.9
$ repo sync -j4 --no-clone-bundle |
Raspberry Pi development kit | |
IPSTB Reference board | Access to repositories hosting code and binaries for reference board |
Peripherals | TV, Keyboard |
Background Color | ||
---|---|---|
| ||
Environment |
Expand | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
Rpi & IPSTB similarities:
Difference between Raspberry Pi (Rpi) and IPSTB:
|
The instructions provided below are meant to be executed via the command line on an Ubuntu machine
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
# essential packages installation
# super user mode is required
# major essential packages
sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib g++-multilib build-essential chrpath socat bison curl cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm |
Code Block | ||||
---|---|---|---|---|
| ||||
sudo dpkg-reconfigure dash |
Select “No”
To choose bash, when the prompt asks if you want to use dash as the default system shell - select “No”
Upgrade your Git version to 1.8.x or higher
Once git is installed, configure your name and email using the below commands
Code Block | ||||
---|---|---|---|---|
| ||||
# review your existing configuration
git config --list --show-origin
# configure user name and email address
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
# configure git cookies. Needed for Gerrit to only contact the LDAP backend once.
git config --global http.cookieFile /tmp/gitcookie.txt
git config --global http.saveCookies true |
In order to use Yocto build system, first you need to make sure that repo is properly installed on the machine:
Code Block | ||||
---|---|---|---|---|
| ||||
# create a bin directory
mkdir ~/bin
export PATH=~/bin:$PATH
# Download the repo tool and ensure that it is executable
curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo |
Credential configuration (Only for Amlogic reference board)
Note: it is also recommended to put credentials in .netrc when interacting with the repo.
A sample .netrc file is illustrated below
machine code.rdkcentral.com login <YOUR_USERNAME> password <YOUR_PASSWORD> |
---|
Background Color | ||
---|---|---|
| ||
Build |
AUI Tab Group |
---|
The generated image resides under the directory Enabled the distro(ipclient) for IPSTB as a setup environment option, so during build time we can pass this as an argument. The generated image resides under the directory |
Background Color | ||
---|---|---|
| ||
Flash image and bring up |
AUI Tab Group |
---|
Flash image1. Insert an SD card in the SD card port of the USB SD card reader (or Laptop). Prefer to use 32gb sd card and there should be minimum 12gb free space available in the device . 2. Verify that the SD card has been detected by executing either of the commands listed below 3. Type the following command to ensure that the partitions, if present, on the SD card are not mounted 4. Repeat the below command to unmount all the mounted partition present on the SD card. 5. Execute the following command to flash the image on the SD card 6. Remove the SD card and insert it to the Raspberry Pi SD card slot 7. Power on the Rpi and Bring up the device
Accessing Raspberry Pi
eg :- gst-launch-1.0 playbin uri=aamp://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8 video-sink=westerossink Flash imageThere are multiple methods to flash/upgrade image in an Amlogic reference board. For the ease of process, we will use the USB based method, which is easy as well as helps to recover even the devices that went into a bad state. The method is as simple as copying a configuration file and the image to flash in a USB and restart the device and run a command
There are other image upgrade methods also available. Please refer to https://wiki.rdkcentral.com/display/RDK/Build+and+Flashing+Steps for more details Accessing Amlogic STB
aamp-cli https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel-dash-playready.ism/.mpd |
Background Color | ||
---|---|---|
| ||
Yocto recipe structure of relevant components |
Below is the major meta-layers specific to Raspberry Pi.
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Below is the major meta-layers specific to Amlogic IPSTB
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Background Color | ||
---|---|---|
| ||
Setup and Develop Thunder plugin |
Steps involved in implementing new RDK services Plug-In
RDK components implemented as Thunder plugins are called as RDKServices. it is developed based on the Thunder (WPE) Framework. Services each other or a particular service can be COMRPC for (communication between plugins) or JSONRPC (for external communication). It has a web-based controller UI.
Reference : https://github.com/rdkcentral/rdkservices/pull/960
In RDK services -plugins workspace:
Cloned from https://github.com/rdkcentral/rdkservices
$ git clone https://github.com/rdkcentral/rdkservices
PluginTemplate/
├── CMakeLists.txt
├── PluginTemplate.config
├── PluginTemplate.cpp
├── PluginTemplate.h
├── PluginTemplate.json
├── Module.cpp
├── Module.h
├── README.md
├── cmake
| ├── FindDS.cmake
│ └── FindIARMBus.cmake
└── doc
└── PluginTemplate.md
This file contains the plugin's information like schema, information and interface json file.
Syntax :
Code Block | ||
---|---|---|
| ||
{
{
"$schema": "plugin.schema.json",
"info": {
"title": "Plugin Name Plugin",
"callsign": "PluginName",
"locator": "libWPEFrameworkPluginName.so",
"status": "production",
"description": "The PluginName plugin allows retrieving of various plugin-related information.",
"version": "1.0"
},
"interface": {
"$ref": "{interfacedir}/PluginName.json#"
}
} |
eg: PluginTemplate.json
Code Block | ||
---|---|---|
| ||
{
"locator":"libWPEFrameworkPluginTemplate.so",
"classname":"PluginTemplate",
"precondition":[
"Platform"
],
"callsign":"org.rdk.PluginTemplate",
"autostart":false
} |
<PluginName>.config.config files are files used to configure the parameters and initial settings for some computer programs.
Code Block | ||||
---|---|---|---|---|
| ||||
set (autostart false) #we are setting autostart condition disable
set (preconditions Platform)
set (callsign "org.rdk.PluginTemplate") #The callsign name was given to an instance of a plugin.
#One plugin can be instantiated multiple times. but each instance, the instance-name "callsign" must be unique. here we using org.rdk.PluginTemplate. |
Declare the plugin class in this which should contain all the structures, variables, and methods which are needed for plugin implementation.
Code Block | ||||
---|---|---|---|---|
| ||||
namespace WPEFramework {
namespace Plugin {
class PluginName : public PluginHost::IPlugin, public PluginHost::IWeb, public PluginHost::JSONRPC {
public:
PluginName()
: _skipURL(0)
, _service(nullptr)
, _subSystem(nullptr)
{
RegisterAll();
}
virtual ~PluginName()
{
UnregisterAll();
}
}
---------------------------------------
---------------------------------------
}
} |
eg: PluginTemplate.h
for more information refer PluginTemplate.h
This class does contain all the definitions for the methods declared in the PluginTemplate.h and those definitions should be defined inside the below namespace.
The plugin should register using service registration MACRO as declared below :
Code Block | ||||
---|---|---|---|---|
| ||||
namespace WPEFramework {
namespace Plugin {
SERVICE_REGISTRATION(Plugin, 1, 0);
---------------------------------------
---------------------------------------
---------------------------------------
}
} |
To initialize and deinitialize or activate or deactivate handler for the plugin services :
Code Block | ||||
---|---|---|---|---|
| ||||
const string PluginTemplate::Initialize(PluginHost::IShell* /* service */)
{
//shared pointer initialized
//initialize external library
LOGINFO();
return (string());
}
void PluginTemplate::Deinitialize(PluginHost::IShell* /* service */)
{
//shared pointer deinitialized
//deinitialize external library
LOGINFO();
} |
eg:
Code Block | ||||
---|---|---|---|---|
| ||||
namespace WPEFramework {
namespace Plugin {
SERVICE_REGISTRATION(Plugin, 1, 0);
//registration
//All the methods declared in Plugin.h should be registered here
//initialize and deinitialize the handlers for the plug-in service
//All the methods declared in Plugin.h should be defined here
}
} |
Using the CMake utility this file contains the task needed to be done to make a plug-in. Also contains packages, libraries needed to compile, its path, and other plugin-in configuration option.
This file contains a set of directives and instructions describing the project's source files and targets (executable, library, or both).
Code Block | ||||
---|---|---|---|---|
| ||||
set(PLUGIN_NAME PluginTemplate) # to set a environment variable set(<variable> <value>)
set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME})
find_package(${NAMESPACE}Plugins REQUIRED) # to Finds and loads settings from an external project.
#Adds a library target called <name> to be built from the source files listed in the command invocation. The <name> corresponds to the logical target name and must be globally unique within a project.
add_library(${MODULE_NAME} SHARED
PluginTemplate.cpp
Module.cpp
../helpers/utils.cpp) |
In rdkservices directory open CmakeLists.txt :
$ vi CmakeLists.txt
add these lines ( by default its disabled ) :
Code Block | ||
---|---|---|
| ||
if(PLUGIN_PLUGINTEMPLATE)
add_subdirectory(PluginTemplate)
endif() |
it will invoke your CMakeLists.txt file present in your plugin directory.
To include plugintemplate plugin in build sequence, Open rdkservices recipe file and add below line. By default; its configured to be disabled while building rdkservices.
$ vi meta-rdk-video/recipes-extended/rdkservices/rdkservices_git.bb
Code Block | ||
---|---|---|
| ||
PACKAGECONFIG[plugintemplate] = " -DPLUGIN_PLUGINTEMPLATE=OFF,-DPLUGIN_PLUGINTEMPLATE=ON, " |
To include the plugin in rdkservises build; add the same in packageconfig in rdkservices recipe:
PACKAGECONFIG += " plugintemplate"
to compile and install in build directory :
$ bitbake -c compile -f rdkservices
once build complete copy .json, .so file into raspberry Pi.
Copy the Plugin.json (eg: PluginTemplate.json) file to “/etc/WPEFramework/plugins” in raspberry Pi
Copy the plugin library (libWPEFrameworkPluginTemplate.so) to “/usr/lib/wpeframework/plugins”
so that the controller plugin identify it and list it in the WebUI ( controller UI ).
Controller UI is a web UI that can be launched from a host machine's (machine under the same network where Rpi resides) browser. This UI can be loaded with the Rpi box's IP address with Thunder's port number configured (here). RDKServices uses 9998 as port.
URL: http://<IP address of the Target device>:9998
Defalut page of Controller UI shall be loaded on web-browser and that will be of Controller tab. Controller tab allows all available plugins to be enabled or disabled.
Each RDK Service can be validated through JSON RPC Commands through HTTP. It has a request and response in JSN format.
Note: the argument is case sensitive.
"callsign":"org.rdk.PluginTemplate"
Function | Request | Response | Remarks |
---|---|---|---|
Activate controller | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{ "jsonrpc":"2.0", "id":3, "method":"Controller.1.activate", "params":{"callsign":"org.rdk.PluginTemplate"} }' | {"jsonrpc":"2.0","id":3,"result":{"success":true}} | |
Deactivate controller | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{ "jsonrpc":"2.0", "id":3, "method":"Controller.1.deactivate", "params":{"callsign":"org.rdk.PluginTemplate"} }' | {"jsonrpc":"2.0","id":3,"result":{"success":true}} | |
getPluginStatus | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getPluginTemplateStatus"}' | {"jsonrpc":"2.0","id":3,"result":{"connection status from plugin":["CONNECTED"],"success":true}} | |
getPluginTemplateList | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getPluginTemplateList"}' | {"jsonrpc":"2.0","id":3,"result":{"Supported plugin list":["plug-A","plug-B","plug-C","plug-D","plug-E"],"success":true}} | |
getPluginTemplateInfo | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getPluginTemplateInfo", "params":{"plugin_name":"plug-A"}}' | {"jsonrpc":"2.0","id":3,"result":{"supportedTvResolutions":["xyz-plugin","no:430HT5"],"success":true}}root@raspberrypi-rdk-mc:~# | |
event API when hdmi connected | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getConnectedVideoDisplays"}' | {"jsonrpc":"2.0","id":3,"result":{"connectedVideoDisplays":["HDMI0"],"success":true}}root@raspberrypi-rdk-mc:~# | |
event API when hdmi not connected | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getConnectedVideoDisplays"}' | {"jsonrpc":"2.0","id":3,"result":{"connectedVideoDisplays":[],"success":true}}root@raspberrypi-rdk-mc:~# |
Code Block | ||||
---|---|---|---|---|
| ||||
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{ "jsonrpc":"2.0", "id":3, "method":"Controller.1.activate", "params":{"callsign":"org.rdk.PluginTemplate"} }'
{"jsonrpc":"2.0","id":3,"result":{"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{ "jsonrpc":"2.0", "id":3, "method":"Controller.1.deactivate", "params":{"callsign":"org.rdk.PluginTemplate"} }'
{"jsonrpc":"2.0","id":3,"result":{"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getPluginTemplateStatus"}'
{"jsonrpc":"2.0","id":3,"result":{"connection status from plugin":["CONNECTED"],"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getPluginTemplateList"}'
{"jsonrpc":"2.0","id":3,"result":{"Supported plugin list":["plug-A","plug-B","plug-C","plug-D","plug-E"],"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getPluginTemplateInfo", "params":{"plugin_name":"plug-A"}}'
{"jsonrpc":"2.0","id":3,"result":{"supportedTvResolutions":["xyz-plugin","no:430HT5"],"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getConnectedVideoDisplays"}'
{"jsonrpc":"2.0","id":3,"result":{"connectedVideoDisplays":["HDMI0"],"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"org.rdk.PluginTemplate.1.getConnectedVideoDisplays"}'
{"jsonrpc":"2.0","id":3,"result":{"connectedVideoDisplays":[],"success":true}}root@raspberrypi-rdk-mc:~#
root@raspberrypi-rdk-mc:~# |
OUT OF PROCESS Plugin
Here the plugin is developed as out of process, which runs as a separate thread from WPEFramework. Services each other or a particular service can be COMRPC ( for communication between plugins) or JSONRPC (for external communication). it has a web-based controller UI.
OutOfProcessPlugin/
├── CMakeLists.txt
├── OutOfProcessPlugin.config
├── OutOfProcessPlugin.cpp
├── OutOfProcessPlugin.h
├── OutOfProcessPluginJsonRpc.cpp
├── OutOfProcessPlugin.json
├── Module.cpp
├── Module.h
├── OutOfProcessPlugin.md
<PluginName>.json
This file contains the plugin's information like schema, information and interface json file. Here the outofprocess will be true, which indicates that the plugin run as a seperate process.
eg: OutOfProcessPlugin.json
Code Block | ||
---|---|---|
| ||
{
"locator":"libWPEFrameworkOutOfProcessPlugin.so",
"classname":"OutOfProcessPlugin",
"precondition":[
"Platform"
],
"autostart":true,
"configuration":{
"root":{
"outofprocess":true
}
}
} |
<PluginName>.config
.config files are files used to configure the parameters and initial settings for some computer programs.
Here outofprocess is set to true, to make plugin as out of process plugin.
Code Block | ||
---|---|---|
| ||
set (autostart true)
set (preconditions Platform)
map()
kv(outofprocess true)
end()
ans(rootobject) |
<PluginName>.h
Declare the plugin class in this which should contain all the structures, variables, and methods which are needed for plugin implementation.
Code Block | ||
---|---|---|
| ||
namespace WPEFramework {
namespace Plugin {
class PluginName : public PluginHost::IPlugin, public PluginHost::IWeb, public PluginHost::JSONRPC {
public:
PluginName()
: _skipURL(0)
, _service(nullptr)
, _subSystem(nullptr)
{
RegisterAll();
}
virtual ~PluginName()
{
UnregisterAll();
}
}
---------------------------------------
---------------------------------------
}
} |
<PluginName>.cpp
This class does contain all the definitions for the methods declared in the Plugin.h and those definitions should be defined inside the below namespace.
The plugin should register using service registration MACRO as declared below :
Code Block | ||
---|---|---|
| ||
namespace WPEFramework {
namespace Plugin {
SERVICE_REGISTRATION(Plugin, 1, 0);
---------------------------------------
---------------------------------------
---------------------------------------
}
} |
To initialize and deinitialize or activate or deactivate handler for the plugin services :
Code Block | ||
---|---|---|
| ||
const string OutOfProcessPlugin::Initialize(PluginHost::IShell* /* service */)
{
//shared pointer initialized
//initialize external library
LOGINFO();
return (string());
}
void OutOfProcessPlugin::Deinitialize(PluginHost::IShell* /* service */)
{
//shared pointer deinitialized
//deinitialize external library
LOGINFO();
} |
Process handler plugin services to receive request and sent responses based on the services :
Code Block | ||
---|---|---|
| ||
Core::ProxyType<Web::Response> OutOfProcessPlugin::Process(const Web::Request &request)
{
Core::ProxyType<Web::Response> result(PluginHost::IFactories::Instance().Response());
//Handle the service request and send the responses
-----------------
-----------------
return result;
} |
eg: refer OutOfProcessPlugin.cpp
<PluginNameJsonRpc>.cpp>
The PluginNameJsonRpc file contains the registration for methods and properties which are declared in PluginName.h
Code Block | ||
---|---|---|
| ||
namespace WPEFramework {
namespace Plugin {
//registration
void OutOfProcessPlugin::RegisterAll()
{
// methods and properties declared in Plugin.h are registered here
-------------------
-------------------
}
void OutOfProcessPlugin::UnregisterAll()
{
}
}
} |
CMakeLists.txt
Using the CMake utility this file contains the task needed to be done to make a plug-in. Also contains packages, libraries needed to compile, its path, and other plugin-in configuration option.
This file contains a set of directives and instructions describing the project's source files and targets (executable, library, or both).
Code Block | ||
---|---|---|
| ||
set(PLUGIN_NAME OutOfProcessPlugin) # to set a environment variable set(<variable> <value>)
set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME})
find_package(${NAMESPACE}Plugins REQUIRED) # to Finds and loads settings from an external project.
#Adds a library target called <name> to be built from the source files listed in the command invocation. The <name> corresponds to the logical target name and must be globally unique within a project.
add_library(${MODULE_NAME} SHARED
OutOfProcessPlugin.cpp
OutOfProcessPluginJsonRpc.cpp
Module.cpp) |
The Code flow, Compilation and Install steps are similar to the PluginTemplate.
The last step,
Copy the Plugin.json (eg: OutOfProcessPlugin .json) file to “/etc/WPEFramework/plugins” in Raspberry Pi
Copy the plugin library (libWPEFrameworkOutOfProcessPlugin.so) to “/usr/lib/wpeframework/plugins”
so that the controller plugin identify it and list it in the WebUI ( controller UI ).
Controller UI is a web UI that can be launched from a host machine's (machine under the same network where Rpi resides) browser.
URL: http://<IP address of the Target device>:9998
Each RDK Service can be validated through JSON RPC Commands through HTTP. It has a request and response in JSON format.
Note: the argument is case sensitive.
"callsign":"OutOfProcessPlugin"
Function | Request | Response | Remarks |
---|---|---|---|
Activate controller | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{ "jsonrpc":"2.0", "id":3, "method":"Controller.1.activate", "params":{"callsign":"OutOfProcessPlugin"} }' | {"jsonrpc":"2.0","id":3,"result":{"success":true}} | |
Deactivate controller | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{ "jsonrpc":"2.0", "id":3, "method":"Controller.1.deactivate", "params":{"callsign":"OutOfProcessPlugin"} }' | {"jsonrpc":"2.0","id":3,"result":{"success":true}} | |
Get fps | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"OutOfProcessPlugin.1.fps"}' | {"jsonrpc":"2.0","id":3,"result":32} | |
Get plugin id | curl http://127.0.0.1:9998/jsonrpc --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0", "id":3, "method":"OutOfProcessPlugin.1.getpluginid"}' | {"jsonrpc":"2.0","id":3,"result":6501} |
Background Color | ||
---|---|---|
| ||
Interface with other RDK services |
RDK components implemented as Thunder plugins are called as RDKServices. It is developed based on the Thunder (WPE) Framework. Services each other or a particular service can be COMRPC ( for communication between plugins) or JSONRPC (for external communication).i.e.
COMRPC is used to communicate between the plugins (out of process) or to communicate for larger data.
JSONRPC is used to fetch/update info to or from plugins externally (most of the plugins provide this in interface, similar to ReST API) also it can be used from applications.
For instance please see below Bluetooth plugin's pair method with JSONRPC interface.
Event | Description |
---|---|
BluetoothState: PAIRING_CHANGE | Triggers onStatusChanged event when the device gets paired to given device ID. |
BluetoothState: PAIRING_FAILED | Triggers onRequestFailed event, when the device is unable to pair. |
Name | Type | Description |
---|---|---|
params | object | |
params.deviceID | string | ID that is derived from the Bluetooth MAC address. 6 byte MAC value is packed into 8 byte with leading zeros for first 2 bytes |
Name | Type | Description |
---|---|---|
result | object | |
result.success | boolean | Whether the request succeeded |
Code Block | ||||
---|---|---|---|---|
| ||||
{
"jsonrpc": "2.0",
"id": 42,
"method": "org.rdk.Bluetooth.1.pair",
"params": {
"deviceID": "61579454946360"
}
} |
Code Block | ||||
---|---|---|---|---|
| ||||
{
"jsonrpc": "2.0",
"id": 42,
"result": {
"success": true
}
} |
For more details please refer : https://github.com/rdkcentral/rdkservices/blob/sprint/2107/Bluetooth/doc/BluetoothPlugin.md#pair-method
Code Block | ||
---|---|---|
| ||
this.thunderJS.call('org.rdk.Bluetooth', 'pair', { deviceID: deviceIDval },
(err, result) => {
if (err) {
Log.info('\n Bluetooth Pair error' + JSON.stringify(err))
} else {
Log.info('Pairing success' + JSON.stringify(result))
}
}
) |
To know more about how to implement JSONRPC inerface using ThunderJS in JS environment please see https://github.com/rdkcentral/ThunderJS/blob/master/readme.md
Background Color | ||
---|---|---|
| ||
Interface with Lightning apps |
ThunderJS is used to make easy to make API calls to Thunder (WPEframework) over a Websocket connection. ThunderJS can also be used to listen to (and act upon) notifications broadcasted by Thunder. ThunderJS is an isomorphic library, which means it can be used in a browser environment as well as a NodeJS environment.
Lightning is a Javascript TV app development framework based on NodeJS environment. So ThunderJS can be easily integrated to the Lightning apps.
ThunderJS dependencies can be added manually to the lightning projects by adding ‘"ThunderJS": "github:rdkcentral/ThunderJS",’ to the package.json under ‘devDependencies’ and then run ‘npm install’.
OR
ThunderJS can be installed into your project via NPM command. Then the package.json will be updated with the thunder dependency "npm install github:rdkcentral/ThunderJS"
Snippet of package.json is given below .To use the ES6 syntax, we need add the Babel dependency also.
Code Block | ||
---|---|---|
| ||
}
},
"devDependencies": {
"@babel/core": "^7.7.2",
"ThunderJS": "github:rdkcentral/ThunderJS",
"babel-eslint": "^10.0.3",
"dashjs": "^3.1.3",
"eslint": "^6.6.0",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-prettier": "3.1.1",
"hls.js": "^0.13.2",
"husky": "^3.1.0",
"lint-staged": "^9.4.3"
"prettier": "^1.19.1"
}
} |
Next you can import the ThunderJS dependency into your own script like given below.
import ThunderJS from 'ThunderJS',
The library can be initialised by passing the IP, port and other parameters mentioned below
Code Block | ||
---|---|---|
| ||
const config = {
host: '192.168.1.100', // defaults to localhost,
port: 2020, // defaults to 80 endpoint: '/api', // defaults to '/jsonrpc'
protocol: 'wss://', // defaults to 'ws://'
subprotocols: 'notification', // WebSocket sub-protocols, defaults to 'notification'
}
const thunderJS = ThunderJS(config) |
Example:
Code Block | ||
---|---|---|
| ||
this.config = {
host: '127.0.0.1',
port:'9998'
}
try {
this.thunderJS = ThunderJS(this.config)
} catch (err) {
Log.error('Error in initialising the Thunder JS' , err)
|
The library supports 2 ways of making API calls, depending on your coding style preferences.
Option 1 - Argument based
AUI Tab Group |
---|
The result can be processed in two ways also
AUI Tab Group |
---|
Example for Argument based call for Bluetooth plugin is given below where the result is processed in callback based method
Bluetooth plugin pair method - https://github.com/rdkcentral/rdkservices/blob/sprint/2107/Bluetooth/doc/BluetoothPlugin.md#pair-method
Corresponding implementation in ThunderJS
Code Block | ||
---|---|---|
| ||
this.thunderJS.call('org.rdk.Bluetooth', 'pair', { deviceID: deviceIDval },
(err, result) => {
if (err) {
Log.info('\n Bluetooth Pair error' + JSON.stringify(err))
} else {
Log.info('Pairing success' + JSON.stringify(result))
}
}
) |
Notifications
Thunder (WPEframework) broadcasts notifications when events ocur in the system. However it will only broadcast those events that the client has subscribed to.
ThunderJS makes it easy to subscribe to specific events, and execute a callback-function upon every notification of each event.
Example for notification event subscriptions is given below.
Bluetooth onDiscovered event - https://github.com/rdkcentral/rdkservices/blob/sprint/2107/Bluetooth/doc/BluetoothPlugin.md#ondiscovereddevice-event
Corresponding implementation in the Lightning App
Code Block | ||
---|---|---|
| ||
/**
* Event listener to listen to device discovered
*/
this.thunderJS.on('org.rdk.Bluetooth','onDiscoveredDevice',notification =>{
Log.info('<<Device discovered event>>'+JSON.stringify(notification))
})
/** |
$ cd $(RDK_DIR)
$ export LOCAL_BUILD=
1
$ source meta-amlogic/aml-setenv.sh
You're building on Linux
Lunch menu...pick a combo:
1
. mesons4-lib32-ap222
2
. mesons4-lib32-ap223
3
. mesons4-lib32-ap229
4
. mesons4-lib32-aq222
5
. mesons4-lib32-aq223
6
. mesonsc2-
5.4
-lib32-ah212
7
. mesonsc2-
5.4
-lib32-ah212-hybrid
8
. mesonsc2-
5.4
-lib32-ah212-vmx
9
. mesonsc2-
5.4
-lib32-ah219
10
. mesonsc2-
5.4
-lib32-ah232
11
. mesonsc2-
5.4
-lib32-ah232-irdeto
12
. mesonsc2-
5.4
-lib32-ah232-nagra
13
. mesonsc2-
5.4
-lib32-ah232-synamedia
Which would you like? [
2
]
4
$ bitbake lib32-rdk-generic-mediaclient-image
Other way:
Code Block | ||
---|---|---|
| ||
$ repo init --no-clone-bundle -u https://code.rdkcentral.com/r/collaboration/oem/skyworth/skyworth-aml905X2-manifests -b rdk-next -m sc2-rdkservices-restricted.xml --repo-branch=v2.9
$ repo sync -j 32
$ source meta-rdk-skyworth-hx4x/setup-environment --hp44h-rdk --restricted --read-write
$ bitbake lib32-skyworth-generic-mediaclient-image |
1) Using Burning tool
Keep pressing enter to stop at sc2_hp44h#
Connect the usb-usb connector and launch Aml_Burn_Tool V3.
sc2_hp44# run update
Burning tool should show connected. Select image and flash.
2) MfrUtils
Download the image to /data/ path on the device.
mfrUtil -u /data/aml_upgrade_package.img
3) Using firmware update plugin.
Please refer to Firmware Control plugin methods to flash through thunder plugin.
4) USB upgrade
Copy the aml_sdc_burn.ini and image to USB.
Connect USB to the device and stop the device at the boot prompt. ie sc2_hp44h#
usb_burn aml_sdc_burn.ini
NOTE: Please reach out to Skyworth for aml_sdc_burn.ini
https://wiki.rdkcentral.com/display/RDK/Firmware+Upgrade+through+XCONF+Server
ToDo: Alanyse what to add from the above link
From metro doc :- It is ok to take generic content from metro doc but if we are referring to some custom code which metro has ,it is better to avoid it (but can be accomodated as a last sort )
Basic skills expected: https://wiki.rdkcentral.com/display/RDK/Join+RDK
relevant RDK links: https://wiki.rdkcentral.com/display/RDK/Important+Links
hardware requirements: https://wiki.rdkcentral.com/display/RDK/How+to+Build#HowtoBuild-BuildSetupInstructions - Prerequisites
same as RPI,
Belongs to Amlogic
Amlogic→ contact Akhil
Add Diff between RPI & IPSTB Ref box?
check with rajkumar IPSTB is ready or not?
Amlogic→ contact Akhil
It belongs to meta-rdk-ext,met-rdk-video,meta-rdk-cmf.
Yocto layer structure for RDKservices:
this is the recipe where we can find rdkservices recipe in the meta-rdk-video layer.Based upon requirements it is adding in different meta layers 1 is meta-rdk-ext.Similarly broadcom also extended those one and for cmf some restrictions that is also plotted in.Not sure incorporate all like meta-rdk-ext,met-rdk-video,meta-rdk-cmf or meta-rdk-video is fine.
Ask deepthi like "which meta layer it is pointed to?Is this the correct approach?structure format ?"
May be Hello world we can take it.
Check with deepthi → check for template.
Template+Hello world example can give.
template : Fasil
Point of contact → krishnapriya
How they are using ThunderJS to communicate.
Can add: How sample application how it can interact like using some nodes .
Contact: Krishnapriya/Abhija
Abhija created page for systemservices
As per Lp : requires sometime assuming the content is not readily available
How somebody can use ThunderJS and interact with RDKServices.