Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
OM2M/Developer
Contents
- 1 Prerequisite
- 2 Build OM2M from source using Eclipse
- 3 Develop a new plug-in
- 4 Test Scenario
Prerequisite
- Eclipse kepler (for RCP and RAP Developers).
- To build the OM2M project into Eclipse, a Tycho m2e connector is needed. Installation of m2e connectors is accomplished as follows: click Window -> Preferences -> maven -> discovery -> open catalog and type Tycho. Check the “Tycho Configurator” checkbox.
Build OM2M from source using Eclipse
Clone The OM2M project
- Select Windiow->Show View -> Other .
- In the dialog box, select the Git view.
- Click on “Clone a Git repository”.
- Clone the OM2M project using the following link: http://git.eclipse.org/gitroot/om2m/org.eclipse.om2m.git. In the first page, enter the mentioned link in the URI’s location field. Click Next .
- In the second page, keep the “master” branch checkbox selected and click Next.
- In the third page, check the “import all existing projects after clone finishes” and click “Finish”.
- The OM2M project is now cloned and is visible on the Git repositories’ and Package’ explorers.
- Now we will add the required libraries. This step will be removed when all third libraries will be validated by Eclipse.
- Download the libraries from this link: http://wiki.eclipse.org/OM2M/Download
- Extract OM2M-libs and add the following libraries to "org.eclipse.om2m" repository as follows:
- "db4o-core-java5-8.1-SNAPSHOT.jar" library under "org.eclipse.om2m.core\libs",
- "obix.jar" library under "org.eclipse.om2m.commons\libs",
- "xsd" folder under "org.eclipse.om2m.commons\src\main\resources".
Build OM2M using maven
- Select “org.eclipse.om2m” package and right click. Select “Run as -> maven install”.
- Two Eclipse products will be generated after a successful built:
- The NSCL product can be found on this directory: "om2m/org.eclipse.om2m/org.eclipse.om2m.site.nscl/target/products/nscl/<os>/<ws>/<arch>"
- The GSCL product can be found on this directory: "om2m/org.eclipse.om2m/org.eclipse.om2m.site.gscl/target/products/gscl/<os>/<ws>/<arch>"
Develop a new plug-in
Create a new plug-in project
- Create a new plug-in project called org.eclipse.om2m.sample.ipu via File → New → Other → Plug-in Project.
- Enter the data as depicted in the following screenshots.
- Uncheck the Create a plug-in using one of the templates checkbook and press the Finish button.
- As result the following project is created.
Convert the plugin into maven project
- Open the build.properties file in XML and update the src attributes as depicted in the following figure.
- Select the created plug-in "org.eclipse.om2m.sample.ipu" → right click → configure → convert to maven project.
- Enter the data as illustrated in the following and press the Finish button.
- Once the plug-in is converted, open the pom.xml file to edit the parent filed.
- Click on "select Parent" icon and enter "org.eclipse.om2m" in the "Enter groupId, artifactId or sh1 prefix or pattern" field.
- Select "org.om2m.eclipse" and press ok.
- We end this step by updating the plug-inf project. For this, select the "org.eclipse.om2m.sample.ipu" project → maven → update project.
Add the plugin as a maven module to the OM2M parent project
- In this part, we will add the created plug-in as a module to the om2m platform:
- Open the pom file of the org.eclipse.om2m package.
- Go to the modules tab and press Add button.
- Select the org.eclipse.ipu.om2m.sample.ipu plug-in and press ok.
- Build the om2m package and its sub-projects. To do this, select the "om2m.org.eclipse" package → right click → Run as → maven install.
- Check the org.eclipse.om2m.sample.ipu was successfully built. At the buid end, we should get this result.
- Remark: To keep the same display pattern for all the platform' plugins, you can add description and name tags to the org.eclipse.om2m.sample.ipu' pom.xml file.
<project> ...... <name>org.eclipse.om2m :: sample ipu</name> <description>org.eclipse.om2m :: sample ipu</description> ..... </project>
Add the plugin to the OM2M product(s)
- The final step consists of adding the created plug-in to one of om2m platform products, i.e the gscl or the nscl executable. In the following, we choose to add the org.eclipse.om2m.sample.ipu plug-in to the gscl product:
- select the org.eclipse.om2m.site.gscl package.
- open the om2m.product file.
- Press Add button and Type org.eclipse.om2m.sample.ipu
- Click on ok button and save.
- Build the om2m package and its sub-projects: select the "om2m.org.eclipse" package -> right click -> Run as -> maven install.
- To check that the "org.eclipse.om2m.sample.ipu" was successfully added to the gscl product, run the gscl and verify in the console if the "org.eclipse.om2m.sample.ipu" is displayed.
Add dependencies
- Open the manifest file of the created plugin and select Dependencies tab.
- Add required dependencies as depicted in the following figure.
The IPU Monitor
The Sensor class
- The sensor class allows us to manage a sensor by recovering its description, and its state.
package org.eclipse.om2m.sample.ipu; import obix.Contract; import obix.Obj; import obix.Op; import obix.Str; import obix.Uri; import obix.io.ObixEncoder; public class Sensor { /** sensor state */ private static int state; /** * Returns an obix XML representation describing the lamp. * @param sclId - SclBase id * @param appId - Application Id * @param stateCont - the STATE container id * @return Obix XML representation */ public static String getDescriptorRep(String sclId, String appId, String stateCont, String aPoCPath) { // oBIX Obj obj = new Obj(); obj.add(new Str("type", "Sensor")); obj.add(new Str("location","Home")); obj.add(new Str("appId",appId)); // OP GetState from SCL DataBase Op opState = new Op(); opState.setName("getState"); opState.setHref(new Uri(sclId+"/"+"applications/"+appId+"/containers/"+stateCont+ "/contentInstances/latest/content")); opState.setIs(new Contract("retrieve")); opState.setIn(new Contract("obix:Nil")); opState.setOut(new Contract("obix:Nil")); obj.add(opState); // OP GetState from SCL IPU Op opStateDirect = new Op(); opStateDirect.setName("getState(Direct)"); opStateDirect.setHref(new Uri(sclId+"/"+"applications/"+appId+"/"+aPoCPath)); opStateDirect.setIs(new Contract("retrieve")); opStateDirect.setIn(new Contract("obix:Nil")); opStateDirect.setOut(new Contract("obix:Nil")); obj.add(opStateDirect); return ObixEncoder.toString(obj); } /** * Returns an obix XML representation describing the current state. * @param appId - Application Id * @param value - current sensor state * @return Obix XML representation */ public static String getStateRep(String appId, int value) { // oBIX Obj obj = new Obj(); obj.add(new Str("type","sensor")); obj.add(new Str("location","Home")); obj.add(new Str("appId",appId)); String strValue = Integer.toString(value); obj.add(new Str("state",strValue)); return ObixEncoder.toString(obj); } /** * Gets SensorState * @return SensorState */ public static void setState(int state) { int Value = 10 + (int)(Math.random()*100); Sensor.state = Value; } }
The Actuator class
- In this tutorial, we take a lamp as an actuator. Let's consider the following Lamp class which is dedicated to handle the information and state.
package org.eclipse.om2m.sample.ipu; import obix.*; import obix.io.ObixEncoder; public class Lamp { /** Lamp state */ private static boolean state = false; /** * Returns an obix XML representation describing the current state. * @param appId - Application Id * @param value - current lamp state * @return Obix XML representation */ public static String getStateRep(String appId, boolean initValue) { // oBIX Obj obj = new Obj(); obj.add(new Str("type","LAMP")); obj.add(new Str("location","Kitchen")); obj.add(new Str("appId",appId)); obj.add(new Bool("state",initValue)); return ObixEncoder.toString(obj); } public static String getDescriptorRep(String sclId, String appId, String stateCont, String aPoCPath) { // oBIX Obj obj = new Obj(); obj.add(new Str("type", "LAMP")); obj.add(new Str("location","Home")); obj.add(new Str("appId",appId)); // OP GetState from SCL DataBase Op opState = new Op(); opState.setName("getState"); opState.setHref(new Uri(sclId+"/"+"applications/"+appId+"/containers/"+stateCont+ "/contentInstances/latest/content")); opState.setIs(new Contract("retrieve")); opState.setIn(new Contract("obix:Nil")); opState.setOut(new Contract("obix:Nil")); obj.add(opState); // OP GetState from SCL IPU Op opStateDirect = new Op(); opStateDirect.setName("getState(Direct)"); opStateDirect.setHref(new Uri(sclId+"/"+"applications/"+appId+"/"+aPoCPath)); opStateDirect.setIs(new Contract("retrieve")); opStateDirect.setIn(new Contract("obix:Nil")); opStateDirect.setOut(new Contract("obix:Nil")); obj.add(opStateDirect); return ObixEncoder.toString(obj); } /** * Gets lampState * @return lampState */ public static boolean getState(String lampId) { return state; } /** * Sets lampState */ public static void setState(boolean state) { Lamp.state = state; } }
The IPU Monitor class
- In the following, we give a snippet of the IpuMonitor class which perform the creation of the required M2M resources on the gscl resource tree to enable simulated M2M devices monitoring.
- The org.eclipse.om2m.sample.ipu.IpuMonitor class locally triggers the SCLService.doRequest method to create applications, containers, and contentInstances resources on the gateway. In this tutorial, we create sensor_0 and lamp_0 application and each one has two containers: Descriptor to store the lamp/ sensor description and Data to store lamp/ senor measured values.
- We simulate a sensor that sends data every two seconds. This is performed by creating a new sensor_0 Data' contentInstance for each publication.
- You notice that when creating a contentInstance of a Desccriptor/ Data Container we use getDescriptorRep getSateRep methods of the Sensor/ Lamp classes described above.
package org.eclipse.om2m.sample.ipu; import obix.*; import obix.io.ObixEncoder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.om2m.commons.resource.Application; import org.eclipse.om2m.commons.resource.ContentInstance; import org.eclipse.om2m.commons.resource.StatusCode; import org.eclipse.om2m.commons.resource.Container; import org.eclipse.om2m.commons.rest.RequestIndication; import org.eclipse.om2m.commons.rest.ResponseConfirm; import org.eclipse.om2m.core.service.SclService; public class IpuMonitor { /** Logger */ private static Log LOGGER = LogFactory.getLog(IpuMonitor.class); /** Sclbase id */ public final static String SCLID = System.getProperty("org.eclipse.om2m.sclBaseId",""); /** Admin requesting entity */ static String REQENTITY = System.getProperty("org.eclipse.om2m.adminRequestingEntity",""); /** Generic create method name */ public final static String METHOD_CREATE = "CREATE"; /** Generic execute method name */ public final static String METHOD_EXECUTE = "EXECUTE"; /** State container id */ public final static String DATA = "DATA"; /** Descriptor container id */ public final static String DESC = "DESCRIPTOR"; /** Discovered SCL service*/ static SclService SCL; public final static String APOCPATH = "ipu"; /** * Constructor * @param scl - discovered SCL */ public IpuMonitor(SclService scl) { SCL=scl; } public void start () { // Create initial resources for the sensor createLampResources("lamp_0", false, APOCPATH); // Create initial resources for the sensor createSensorResources("sensor_0", APOCPATH); } /** * Creates all required resources. * @param appId - Application ID * @param aPoCPath - sensor aPocPath */ public void createSensorResources(String appId, String aPoCPath) { // Create the Application resource ResponseConfirm response = SCL.doRequest(new RequestIndication(METHOD_CREATE,SCLID+ "/applications",REQENTITY,new Application(appId,aPoCPath))); // Create Application sub-resources only if application not yet created // Create DESCRIPTOR container sub-resource SCL.doRequest(new RequestIndication(METHOD_CREATE,SCLID+"/applications/"+appId+ "/containers",REQENTITY,new Container(DESC))); // Create STATE container sub-resource SCL.doRequest(new RequestIndication(METHOD_CREATE,SCLID+"/applications/"+appId+ "/containers",REQENTITY,new Container(DATA))); String content, targetID; // Create DESCRIPTION contentInstance on the DESCRIPTOR container resource content = Sensor.getDescriptorRep(SCLID, appId, DATA, aPoCPath); targetID= SCLID+"/applications/"+appId+"/containers/"+DESC+"/contentInstances"; SCL.doRequest(new RequestIndication(METHOD_CREATE,targetID,REQENTITY, new ContentInstance(content.getBytes()))); while (true) { // Create initial contentInstance on the STATE container resource int initValue = 10 + (int)(Math.random()*100); content = Sensor.getStateRep(appId, initValue); targetID = SCLID+"/applications/"+appId+"/containers/"+DATA+"/contentInstances"; SCL.doRequest(new RequestIndication(METHOD_CREATE,targetID,REQENTITY, new ContentInstance(content.getBytes()))); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * Creates all required resources. * @param appId - Application ID * @param initValue - initial lamp value * @param aPoCPath - lamp aPocPath */ public void createLampResources(String appId, boolean initValue, String aPoCPath) { // Create the Application resource ResponseConfirm response = SCL.doRequest(new RequestIndication(METHOD_CREATE,SCLID+ "/applications",REQENTITY,new Application(appId,aPoCPath))); // Create Application sub-resources only if application not yet created if(response.getStatusCode().equals(StatusCode.STATUS_CREATED)) { // Create DESCRIPTOR container sub-resource SCL.doRequest(new RequestIndication(METHOD_CREATE,SCLID+"/applications/"+appId+ "/containers",REQENTITY,new Container(DESC))); // Create STATE container sub-resource SCL.doRequest(new RequestIndication(METHOD_CREATE,SCLID+"/applications/"+appId+ "/containers",REQENTITY,new Container(DATA))); String content, targetID; // Create DESCRIPTION contentInstance on the DESCRIPTOR container resource content = Lamp.getDescriptorRep(SCLID, appId, DATA, aPoCPath); targetID= SCLID+"/applications/"+appId+"/containers/"+DESC+"/contentInstances"; SCL.doRequest(new RequestIndication(METHOD_CREATE,targetID,REQENTITY, new ContentInstance(content.getBytes()))); // Create initial contentInstance on the STATE container resource content = Lamp.getStateRep(appId, initValue); targetID = SCLID+"/applications/"+appId+"/containers/"+DATA+"/contentInstances"; SCL.doRequest(new RequestIndication(METHOD_CREATE,targetID,REQENTITY, new ContentInstance(content.getBytes()))); } } /** * Creates a ContentInstance resource on STATE container. * @param lampId - Application ID * @param value - measured state */ public static void createContentResource(String lampId, boolean value) { // Creates lampCI with new State String content = Lamp.getStateRep(lampId, value); String targetID = SCLID+"/applications/"+lampId+"/containers/"+DATA+"/contentInstances"; SCL.doRequest(new RequestIndication(METHOD_CREATE,targetID,REQENTITY,new ContentInstance(content.getBytes()))); } /** * Sets the lamp state. * @param appId - Application ID * @param value - measured state */ public static void setLampState(final String appId, String value) { final boolean newState; boolean currentState = Lamp.getState(appId); String str = Boolean.toString(currentState); if(value.equals(str)) { newState = !currentState; createContentResource(appId, newState); } else { newState = Boolean.parseBoolean(value); // Create the CI in the case when the newState is different to the Current Lamp State if (newState != currentState) { createContentResource(appId, newState); } } //Lamps.LAMPS_STATES.set(index, newState); Lamp.setState(newState); } }
The IPU contoller
- The org.eclipse.om2m.sample.ipu.IpuController implements the IpuService interface to enable communications from SCL to the org.eclipse.om2m.sample.ipu plug-in.
- For each Retrieve request, we have to extract the application identifier (appId) from the requestIndication targetID attribute. Then extarct type and index from appId based on the appId template <type>_<index>.
- For each Execute request we have to extract the application appId and the action value from the requestIndication targetID.
package org.eclipse.om2m.sample.ipu; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.om2m.commons.resource.ErrorInfo; import org.eclipse.om2m.commons.resource.StatusCode; import org.eclipse.om2m.commons.rest.RequestIndication; import org.eclipse.om2m.commons.rest.ResponseConfirm; import org.eclipse.om2m.ipu.service.IpuService; public class IpuController implements IpuService { public final static String APOCPATH = "ipu"; private static Log LOGGER = LogFactory.getLog(IpuController.class); public ResponseConfirm doExecute(RequestIndication requestIndication) { String[] info = requestIndication.getTargetID().split("/"); String lampId = info[info.length-3]; String type = lampId.split("_")[0]; String value = info[info.length-1]; String trueCase = "true"; String falseCase = "false"; try { if(type.equals("lamp")) { IpuMonitor.setLampState(lampId, value); if (value.equals(trueCase)) { javax.swing.JOptionPane.showMessageDialog(null, "the lamp is switched on"); } else if (value.equals(falseCase)) { javax.swing.JOptionPane.showMessageDialog(null, "the lamp is switched off"); } return new ResponseConfirm(StatusCode.STATUS_OK); } else{ return new ResponseConfirm(StatusCode.STATUS_NOT_FOUND,type+" Not found"); } } catch (Exception e) { LOGGER.error("IPU Lamp Error",e); return new ResponseConfirm(StatusCode.STATUS_NOT_IMPLEMENTED,"IPU Lamp Error"); } } public ResponseConfirm doRetrieve(RequestIndication requestIndication) { String[] info = requestIndication.getTargetID().split("/"); String appId = info[info.length-2]; String type= appId.split("_")[0]; int contvalue; boolean value; String content=null; try { if (type.equals("sensor")){ // Get a random Value for the sensor contvalue = 10 + (int)(Math.random()*100); content = Sensor.getStateRep(appId, contvalue); } else if (type.equals("lamp")){ // Get the boolean Value for the lamp value = Lamp.getState(appId); content = Lamp.getStateRep(appId, value); } return new ResponseConfirm(StatusCode.STATUS_OK,content); } catch (Exception e) { LOGGER.error("Hello sample Error",e); return new ResponseConfirm(StatusCode.STATUS_NOT_IMPLEMENTED,"IPU Sample Error" ); } } public ResponseConfirm doUpdate(RequestIndication requestIndication) { return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_IMPLEMENTED, requestIndication.getMethod()+" Method not Implemented")); } public ResponseConfirm doDelete(RequestIndication requestIndication) { return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_IMPLEMENTED, requestIndication.getMethod()+" Method not Implemented")); } public ResponseConfirm doCreate(RequestIndication requestIndication) { return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_IMPLEMENTED, requestIndication.getMethod()+" Method not Implemented")); } public String getAPOCPath() { // TODO Auto-generated method stub return APOCPATH; } }
The IPU Activator
This class customizes the starting and stopping of a the org.eclipse.om2m.sample.ipu plug-in.
package org.eclipse.om2m.sample.ipu; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.om2m.core.service.SclService; import org.eclipse.om2m.ipu.service.IpuService; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; public class Activator implements BundleActivator { /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ /** Logger */ private static Log logger = LogFactory.getLog(Activator.class); /** SCL service tracker */ private ServiceTracker<Object, Object> sclServiceTracker; public void start(BundleContext context) throws Exception { logger.info("Register IpuService.."); context.registerService(IpuService.class.getName(), new IpuController(), null); logger.info("IpuService is registered."); sclServiceTracker = new ServiceTracker<Object, Object>(context, SclService.class.getName(), null) { public void removedService(ServiceReference<Object> reference, Object service) { logger.info("SclService removed"); } public Object addingService(ServiceReference<Object> reference) { logger.info("SclService discovered"); SclService sclService = (SclService) this.context.getService(reference); final IpuMonitor IpuMonitor = new IpuMonitor(sclService); new Thread(){ public void run(){ try { IpuMonitor.start(); } catch (Exception e) { logger.error("IpuMonitor error", e); } } }.start(); return sclService; } }; sclServiceTracker.open(); } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { System.out.println("End Ipu sample"); } }
Test Scenario
- To check that the "sensor_0" and "lamp_0" applications are successfully created, run the NSCL and GSCL products.
- Then go to the GSCL OSGi console and enter the ss command to list all deployed plugins. Start the "org.eclipse.om2m.sample.ipu" plugin (id=28 in this example) by typing the following command: start 28.
- The interworking proxy plug-in creates all required resources to enable to monitor and control sensor and lamp remotely and in a standardized way.
Open the NSCL web interface (127.0.0.1:8080), and move to the GSCL resource tree. Click on the "applications" resource to list all registered applications. You will find the following resources:
- "lamp_0": an application resource enables to handle lamp 0.
- "sensor_0": an application resource enables to handle sensor 0.
This figure illustrates a contentInstance description.
- Execute a command using the following uri: "http://127.0.0.1:8080/om2m/gcl/applications/lamp_0/ipu/true" to switch on the lamp. A message box will appear with the message "The lamp is switched on".