com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_link3' is unknown.

Writing Device Plugins via the Template

Before you begin

  • Clone the WSO2 Carbon Device Management Plugins repository. It will be referred to as <CARBON_DEVICE_MGT_PLUGINS> throughout this document.

    git clone https://github.com/wso2/carbon-device-mgt-plugins.git
  • Build the repo you just cloned.

    cd <CARBON_DEVICE_MGT_PLUGINS>
    mvn clean install

All device types generally have common elements, such as specific attributes, feature management methods, and transport sender mechanisms. WSO2 IoTS identified these common areas and created a template that includes all these details. Using this template you can create your own device plugin. Let's take a quick look at how the device plugin is created from the template:

  1. Configure the device-type-template.xml file to meet your device type's requirement.
  2. If your device type requires specific attributes, create a database and the required table to add these attribute details.
  3. Add the configured device type template to the <CARBON_DEVICE_MGT_PLUGINS>/features/device-types-feature/<DEVICE>-feature-plugin/<ARTIFACT_ID>/src/main/resources/devicetypes directory.
  4. Once you are done with writing the plugin, UI, APIs and Analytics for the device, you need to build <CARBON_DEVICE_MGT_PLUGINS>.
  5. Clone WSO2 IoT Server if you have not done previously and build it.

    git clone https://github.com/wso2/product-iots.git
    cd <PRODUCT_IOTS>
    mvn clean install 
  6. An OSGI bundle for the device type is created in WSO2 CDMF after reading the device.xml file. 

Now you are done with creating the device plugin. It's a very easy with WSO2 IoTS. Let's look at an already implemented scenario to understand this concept.

Sample - writing device plugins

for this guide let's take a look at the already implemented Android plugin device type:

Take a look at the configured device type XML file, before you begin

 Click here to expand.
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
  ~
  ~ WSO2 Inc. licenses this file to you under the Apache License,
  ~ Version 2.0 (the "License"); you may not use this file except
  ~ in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing,
  ~ software distributed under the License is distributed on an
  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  ~ KIND, either express or implied. See the License for the
  ~ specific language governing permissions and limitations
  ~ under the License.
  -->
<DeviceTypeConfiguration name="android">
    <DeviceDetails table-id="AD_DEVICE"/>
    <License>
        <Language>en_US</Language>
        <Version>1.0.0</Version>
        <Text>This is license text</Text>
    </License>
    <ProvisioningConfig>
        <SharedWithAllTenants>false</SharedWithAllTenants>
    </ProvisioningConfig>
    <DataSource>
        <jndiConfig>
            <name>jdbc/MobileAndroidDM_DS</name>
        </jndiConfig>
        <tableConfig>
            <Table name="AD_DEVICE">
                <PrimaryKey>DEVICE_ID</PrimaryKey>
                <Attributes>
                    <Attribute>GCM_TOKEN</Attribute>
                    <Attribute>DEVICE_INFO</Attribute>
                    <Attribute>IMEI</Attribute>
                    <Attribute>IMSI</Attribute>
                    <Attribute>OS_VERSION</Attribute>
                    <Attribute>DEVICE_MODEL</Attribute>
                    <Attribute>VENDOR</Attribute>
                    <Attribute>LATITUDE</Attribute>
                    <Attribute>LONGITUDE</Attribute>
                    <Attribute>SERIAL</Attribute>
                    <Attribute>MAC_ADDRESS</Attribute>
                    <Attribute>DEVICE_NAME</Attribute>
                    <Attribute>OS_BUILD_DATE</Attribute>
                </Attributes>
            </Table>
        </tableConfig>
    </DataSource>
    <Features>
        <Feature code="DEVICE_RING">
            <Name>Ring</Name>
            <Description>Ring the device</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/ring" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="DEVICE_LOCK">
            <Name>Device Lock</Name>
            <Description>Lock the device</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/lock-devices" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="DEVICE_LOCATION">
            <Name>Location</Name>
            <Description>Request coordinates of device location</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/location" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="CLEAR_PASSWORD">
            <Name>Clear Password</Name>
            <Description>Clear current password</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/clear-password" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="DEVICE_REBOOT">
            <Name>Reboot</Name>
            <Description>Reboot the device</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/reboot" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="UPGRADE_FIRMWARE">
            <Name>Upgrade Firmware</Name>
            <Description>Upgrade Firmware</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/upgrade-firmware" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="DEVICE_MUTE">
            <Name>Mute</Name>
            <Description>Enable mute in the device</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/mute" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="NOTIFICATION">
            <Name>Message</Name>
            <Description>Send message</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/send-notification" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="CHANGE_LOCK_CODE">
            <Name>Change Lock-code</Name>
            <Description>Change current lock code</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/change-lock-code" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="ENTERPRISE_WIPE">
            <Name>Enterprise Wipe</Name>
            <Description>Remove enterprise applications</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/enterprise-wipe" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="WIPE_DATA">
            <Name>Wipe Data</Name>
            <Description>Factory reset the device</Description>
            <Operation context="/api/device-mgt/android/v1.0/admin/devices/wipe" method="POST" type="application/json"></Operation>
        </Feature>
        <Feature code="WIFI">
            <Name>Wifi</Name>
            <Description>Setting up wifi configuration</Description>
        </Feature>
        <Feature code="CAMERA">
            <Name>Camera</Name>
            <Description>Enable or disable camera</Description>
        </Feature>
    </Features>
	<TaskConfiguration> //Name needs to be decided <!--DeviceMonitoring-->
       <Enable>true</Enable>
       <Frequency>60000</Frequency> //Name needs to be decided <!--Period-->
       <Operations>
           <Operation>
               <Name>DEVICE_INFO</Name>
               <RecurrentTimes>1</RecurrentTimes> //Name needs to be decided <!--PeriodFactor-->
           </Operation>
           <Operation>
               <Name>APPLICATION_LIST</Name>
               <RecurrentTimes>5</RecurrentTimes>
           </Operation>
           <Operation>
               <Name>DEVICE_LOCATION</Name>
               <RecurrentTimes>1</RecurrentTimes>
           </Operation>
       </Operations>
   </TaskConfiguration>
	<PolicyMonitoring enabled="true"/>
</DeviceTypeConfiguration>

To get a clear understanding of how you need to configure your device type, let's go through the properties of the XML file:

PropertyDescription

DeviceTypeConfiguration

Define the name of the device type. The name of the device you are creating will be mapped with the APIs, UIs and other elements when creating the device plugin.
Example:

<DeviceTypeConfiguration name="android">

DeviceDetails

Every device type will need to store device specific data. Therefore, define the table ID of the database to which you are storing the data in this property.
This is the table we created in the dbbdscripts folder when writing the device feature.
Example:

<DeviceDetails table-id="AD_DEVICE"/>

License

Add the license agreement details under this property. If you are allowing third party users to use the device type you are creating, then this will be very useful to make sure they agree with the terms you mention.
Example:

<License>
    <Language>en_US</Language>
    <Version>1.0.0</Version>
    <Text>This is license text</Text>
</License>
ProvisioningConfig

Your device type can be accessed by many tenants or only the super tenant that is created in WSO2 IoTS by default. Tenant management for a device type is configured within this property.

  • If you define false as the value for SharedWithAllTenants, the device you are creating will only be accessible by the super tenant of WSO2 IoTS.

    <ProvisioningConfig>
        <SharedWithAllTenants>false</SharedWithAllTenants>
    </ProvisioningConfig>
  • If you define true as the value for SharedWithAllTenants, the device you are creating can be accessed by all the tenants created in WSO2 IoTS.

    <ProvisioningConfig>
        <SharedWithAllTenants>true</SharedWithAllTenants>
    </ProvisioningConfig>
 DataSource

The device you create can have attributes specific to the device and you will need to save the data in WSO2 IoTS. This property lets you define the database and the respective table in the database where you will be saving the device specific details.

Note

The ATTRIBUTE property must contain the exact name of the database column. Else when the server is adding the device details to the configured table and the names don't match, you will run into errors.

The attribute details were the column names of the table you created in the dbbdscripts folder and the datasource details were configured in the datasource directory when writing the device feature.

In the android plugin sample, we add the data to the AD_DEVICE table, and the MobileAndroidDM_DS datasource.

<DataSource>
    <jndiConfig>
        <name>jdbc/MobileAndroidDM_DS</name>
    </jndiConfig>
    <tableConfig>
        <Table name="AD_DEVICE">
            <PrimaryKey>DEVICE_ID</PrimaryKey>
            <Attributes>
                <Attribute>GCM_TOKEN</Attribute>
                <Attribute>DEVICE_INFO</Attribute>
                <Attribute>IMEI</Attribute>
                <Attribute>IMSI</Attribute>
                <Attribute>OS_VERSION</Attribute>
                <Attribute>DEVICE_MODEL</Attribute>
                <Attribute>VENDOR</Attribute>
                <Attribute>LATITUDE</Attribute>
                <Attribute>LONGITUDE</Attribute>
                <Attribute>SERIAL</Attribute>
                <Attribute>MAC_ADDRESS</Attribute>
                <Attribute>DEVICE_NAME</Attribute>
                <Attribute>OS_BUILD_DATE</Attribute>
            </Attributes>
        </Table>
    </tableConfig>
</DataSource>
Features

Your device type will carry out various operations. For example, an Android device needs to be locked and unlocked, the device location needs to be fetched and much more. Therefore, the feature management aspect of the device is handled by this property.

You can list out all the features you wish for your device to have using the sub-properties listed below:

  • Feature code: This is used to uniquely identify the operation of a device.
    Moreover, the UI elements of each operation are mapped to the cdmf.unit.device.type.<DEVICE_TYPE>.tyoe-view/public.config.json file via this feature code. For more information, see Writing UI Extensions.
    Example: cdmf.unit.device.type.android.type-view/public/config.json

    <Feature code="DEVICE_LOCK">
  • Name: Define the name you want the operation to be identified.

    <Name>Device Lock</Name>
  • Description: Provide details as to what the operation will do when it's carried out.

    <Description>Lock the device</Description>
  • Operation: Define the API path that will trigger the operation. The operation you define here will be then matched with the API you create for the operation by mapping the resource path and HTTP method provided. To know more, see Writing Device APIs.

    Note

    If you don't define the operation property for a feature, that feature will not be shown as an operation in the device type user interface.

    <Operation context="/api/device-mgt/android/v1.0/admin/devices/lock-devices" method="POST" type="application/json">

     

    • Context: Define the API path
    • method: Define the HTTP method od the operation.
    • type: Define the content-type.
PushNotificationProvider

This property defines the transport over which the device and the server communicates. If the file based property is configured, WSO2 IoTS will read this file and communicate with the device based on the configured transport sender mechanism. If this property is not configured in the device type XML file, WSO2 IoTS will get the required details from platform configurations and you will need to configure the registry accordingly.

Defining this property is useful when configuring the device type to communicate over many transport senders.

The Android plugin does not have this property defined as the transport sender method is configured under the platform configuration of the device. But let's look at a sample configuration:

<PushNotificationProvider type="MQTT">
    <FileBasedProperties>true</FileBasedProperties>
    <!--if file based properties is set to false then the configuration will be picked from platform configuration-->
    <ConfigProperties>
        <Property Name="mqtt.adapter.name">android.mqtt.adapter</Property>
        <Property Name="username">admin</Property>
		<Property Name="password">admin</Property>
        <Property Name="qos">0</Property>
        <Property Name="clearSession">true</Property>
    </ConfigProperties>
</PushNotificationProvider>
TaskConfiguration

This property defines the operation types that needs to be trigger from the server.

<TaskConfiguration> 
    <Enable>true</Enable>
    <Frequency>60000</Frequency> //Name needs to be decided <!--Period-->
    <Operations>
        <Operation>
            <Name>DEVICE_INFO</Name>
            <RecurrentTimes>1</RecurrentTimes> //Name needs to be decided <!--PeriodFactor-->
        </Operation>
        <Operation>
            <Name>APPLICATION_LIST</Name>
            <RecurrentTimes>5</RecurrentTimes>
        </Operation>
        <Operation>
            <Name>DEVICE_LOCATION</Name>
            <RecurrentTimes>1</RecurrentTimes>
        </Operation>
    </Operations>
</TaskConfiguration>
PolicyMonitoring

This property defines whether the device types requires policy compliance monitoring.

<PolicyMonitoring enabled="true"/>

What's next?

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.