A collection of Carbon components are required to create a new device type in WSO2 IoT Server. It is developed simply by plugging various Carbon components that provide different features. The following folder structure is recommended to create the feature, but you are able to customize it to suit your requirement.
Example: The folder structure of the Raspberry Pi plugin that is in the <CARBON_DEVICE_MGT_PLUGINS>/features
directory.
Let's take a look at how each directory contributes to your device type and why it's used:
Agent directory
When enrolling a device with WSO2 IoT Server you require agents to communicate with the device and the server. You can configure the agent and host it on a separate location or have it within WSO2 IoT Server. If you are configuring the agent via WSO2 IoT Server all the agent related files can be included in this directory.Â
Each device type has its own enrollment mechanism. Take a look at the different ways of enrolling devices:
 Example: Configuring an agent for a Raspberry Pi device
Define the device configurations in the deviceConfig.properties as shown below:
Example: Configurations for Raspberry Pi
[Device-Configurations]
server-name=${SERVER_NAME}
owner=${DEVICE_OWNER}
deviceId=${DEVICE_ID}
device-name=${DEVICE_NAME}
controller-context=/raspberrypi/controller
mqtt-sub-topic=${SERVER_NAME}/{owner}/raspberrypi/{deviceId}
mqtt-pub-topic=${SERVER_NAME}/{owner}/raspberrypi/{deviceId}/publisher
https-ep=${HTTPS_EP}
http-ep=${HTTP_EP}
apim-ep=${APIM_EP}
mqtt-ep=${MQTT_EP}
xmpp-ep=${XMPP_EP}
auth-method=token
auth-token=${DEVICE_TOKEN}
refresh-token=${DEVICE_REFRESH_TOKEN}
push-interval=15
Create the sketch.properties. It contains the information for the IoT Server to find the agent template that was explained in step 1 and where to get the zip file when a user clicks download agent.
templates=deviceConfig.properties
zipfilename=RaspberryPiAgent.zip
- You might require scripts to start the downloaded agent. Add all the configurations and files required for the agent in this directory.
Datasources directory
A datasource provides the information that is required for a server to connect to a database or to an external data store.
 Example: raspberrypi-datasources.xml file
<?xml version="1.0" encoding="UTF-8"?>
<datasources-configuration xmlns:svns="http://org.wso2.securevault/configuration">
<providers>
<provider>org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader</provider>
</providers>
<datasources>
<datasource>
<name>RaspberryPi_DB</name>
<description>The datasource used for the RaspberryPi database</description>
<jndiConfig>
<name>jdbc/RaspberryPiDM_DB</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:h2:repository/database/RaspberryPiDM_DB;DB_CLOSE_ON_EXIT=FALSE</url>
<username>wso2carbon</username>
<password>wso2carbon</password>
<driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>
</datasources>
</datasources-configuration>
DB scripts directory
WSO2 IoTS runs on top of WSO2 CDMF. Each device type that you configure to enroll with WSO2 IoTS will have details specific to them. Therefore you need to create the required database scripts in the dbscripts
 folder for these details to be passed into CDMF to create the respective databases in CDMF.
When a plugin is created it will get access to the following common APIs that is made available via WSO2 CDMF. These APIs too will refer to the database to know which fields need to be updated when one of the respective APIs are called. The APIs are:
- Adding a device.
- Updating the device details.
- Getting the device.
- Getting all the devices in WSO2 IoTS.
- Removing the device.
 Click here for a sample implementation of the Raspberry Pi H2 database script.
-- -----------------------------------------------------
-- Table `RASPBERRYPI_DEVICE`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `RASPBERRYPI_DEVICE` (
`RASPBERRYPI_DEVICE_ID` VARCHAR(45) NOT NULL ,
`DEVICE_NAME` VARCHAR(100) NULL DEFAULT NULL,
PRIMARY KEY (`RASPBERRYPI_DEVICE_ID`) );
Device types
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.Â
 Click here to see the Raspberry Pi plugin that's configured using the template.
<DeviceTypeConfiguration name="raspberrypi">
<Features>
<Feature code="bulb">
<Name>Control Bulb</Name>
<Description>Control Bulb on Raspberrypi</Description>
<Operation context="/raspberrypi/device/{deviceId}/bulb" method="POST">
<QueryParameters>
<Parameter>state</Parameter>
</QueryParameters>
</Operation>
</Feature>
</Features>
<ProvisioningConfig>
<SharedWithAllTenants>false</SharedWithAllTenants>
</ProvisioningConfig>
<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">raspberrypi.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="username">admin</Property>
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
<Property Name="qos">0</Property>
<Property Name="scopes"/>
<Property Name="clearSession">true</Property>
</ConfigProperties>
</PushNotificationProvider>
<License>
<Language>en_US</Language>
<Version>1.0.0</Version>
<Text>This is license text</Text>
</License>
</DeviceTypeConfiguration>
p2.inf file
The p2.inf
 file contains the details on copying the files from the P2 repository to the WSO2 IoTS pack.Â
 Click here to see a configured p2.inf file.
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/webapps/,target:${installFolder}/../../deployment/server/webapps/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/raspberrypi/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/agent/,target:${installFolder}/../../resources/sketches/raspberrypi/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/dbscripts/,target:${installFolder}/../../../dbscripts/cdm/plugins/raspberrypi,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/jaggeryapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/jaggeryapps/,target:${installFolder}/../../deployment/server/jaggeryapps/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/datasources/,target:${installFolder}/../../conf/datasources/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../database/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/database/,target:${installFolder}/../../database/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/carbonapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/carbonapps/,target:${installFolder}/../../deployment/server/carbonapps/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/devicetypes/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.raspberrypi_${feature.version}/devicetypes/,target:${installFolder}/../../deployment/server/devicetypes/,overwrite:true);\
instructions.unconfigure = \
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/raspberrypi.war);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/raspberrypi);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../dbscripts/cdm/plugins/raspberrypi);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../resources/sketches/raspberrypi);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../conf/datasources/raspberrypi-datasources.xml);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../database/RaspberryPiDM_DB.h2.db);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.device-view);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.type-view);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.analytics-view);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.realtime.analytics-view);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.platform.configuration);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/carbonapps/raspberrypi.car);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/devicetypes/raspberrypi.xml);\
pom.xml file
Create the pom.xml
file to package the new feature and create the device type as a feature in the P2 repository. The file contains information on the device type and configuration details used by Maven to build the feature.Â
Example: The fully configured pom.xm
l file for the Raspberry Pi sample here.
plugins-deployer.xml file
The plugins-deployer.xml
 contains the information required to create the P2 repository in the device types folder. Configure the <IoT_HOME>/plugins/plugins-deployer.xml
file.
Add the device type feature under the <featureArtifacts>
 tag.
<featureArtifactDef>
{groupID}-plugin:{groupID}.{artifactID}.feature:{version}
</featureArtifactDef>
Example:
<featureArtifactDef>
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.iot.raspberrypi.feature:${carbon.device.mgt.plugin.version}
</featureArtifactDef>
Add the device type feature group under the <features>
 tag.
<features>
<feature>
<id>{groupID}.{artifactID}.feature.group</id>
<version>{version}</version>
</feature>
</features>
Example:
<features>
 <feature>
<id>org.wso2.carbon.device.mgt.iot.raspberrypi.feature.group</id>
<version>${carbon.device.mgt.plugin.version}</version>
</feature>
</features>
What's next?
Now you are done creating the folder structure and creating the respective databases and datasources required for your device type. You can proceed to configure your device type further as explained below: