主頁 >  其他 > Thingworx自定義擴展開發

Thingworx自定義擴展開發

2021-07-30 08:36:18 其他

Create An Extension

官方鏈接:https://developer.thingworx.com/en/resources/guides/eclipse-plugin-thingworx-extension-development-tutorial

Overview

Build extensions quickly and extend your application functionality with the Eclipse Plugin.

GUIDE CONCEPT

Extensions enable you to quickly and easily add new functionality to an IoT solution. Extensions can be service (function/method) libraries, connector templates, functional widgets, and more.

The Eclipse Plugin for ThingWorx Extension Development (Eclipse Plugin) is designed to streamline and enhance the creation of extensions for the ThingWorx Platform. The plugin makes it easier to develop and build extensions by automatically generating source files, annotations, and methods as well as updating the metadata file to ensure the extension can be imported.

These features allow you to focus on developing functionality in your extension, rather than worrying about getting the syntax and format of annotations and the metadata file correct.

THINGS USED IN THIS GUIDE

Environment:

This guide may be completed within any environment where you have access to the ThingWorx Foundation server. This guide is based on the Extension SDK version 8.3.

This includes both the hosted evaluation server, as well as the downloadable trial. You can use either Gradle or Ant to build your ThingWorx Extension Project.

Before you start, ensure you have the following software installed.

  • Download Java Development Kit: jdk1.8.
  • Download Eclipse Photon for Java Developers.

Completed Example: You are provided a complete example that can be utilized as a reference for completion as you go through the guide or for insight into how the following steps can be completed.

NOTE: If you use Gradle as the build tool, in your Eclipse application, download the Gradle STS IDE plugin from Help->Eclipse Marketplace, then restart your workspace.

Step 1: Completed Example

Download the completed files for this tutorial: Extension Sample Files.

The ExtensionSampleFiles.zip file provided to you contains a completed example of the scenario you will be walk through in the following steps. Utilize this file if you would like to see a finished example as a reference or if you become stuck during this guide and need some extra help.

Step 2: Download Plugin and SDK

The ThingWorx Extension SDK provides supported classes and APIs to build Java-based extensions. The APIs included in this SDK allow manipulation of ThingWorx platform objects to create Java based extensions that can extend the capability of the existing ThingWorx platform.

The Eclipse Plugin assists in working with the Extension SDK to create projects, entities, and samples.

  1. Download the Eclipse Plugin from ThingWorx Marketplace.
  2. Download Extension SDK from ThingWorx Marketplace.
  3. Make a note of the directory where the plugin and the extension SDK are stored. The path of the directory will be required in upcoming steps. Do not extract the zip files.

Step 3: Install and Configure

Before you install the plugin, ensure that software requirements are met for proper installation of the plugin.

  1. Open Eclipse Mars and choose a suitable directory as a workspace.

  2. Go to the menu bar of the Eclipse window and select Help->Install New Software…

  3. After the Install window opens, click Add to add the Eclipse Plugin repository.

  4. Click Archive… and browse to the directory where the Eclipse Plugin zip file is stored and click Open.

  5. Enter a name (for example, Eclipse Plugin).

  6. Click OK.

NOTE: Do not extract this zip file.

  1. Ensure that the Group items by category checkbox is not selected.

  2. Select ThingWorx Extension Builder in the items list of the Install window.

  3. Click Next and the items to be installed are listed.

  4. Click Next and review the license agreement.

  5. Accept the license agreement and click Finish to complete the installation process.

NOTE: If a warning for unsigned content is displayed, click OK to complete the installation process.

  1. Restart Eclipse.

  2. When Eclipse starts again, ensure that you are in the ThingWorx Extension perspective. If not, select Window->Perspective->Open Perspective->Other->ThingWorx Extension, then click OK.

NOTE: Opening any item from File->New->Other…->ThingWorx will also change the perspective to ThingWorx Extension.

You are ready to start a ThingWorx Extension Project!

Step 4: Create Extension Project

In this tutorial, you will create a ThingWorx extension that retrieves weather information using OpenWeatherMap API.

Create Account

In this part of the lesson, you will create a free account in OpenWeatherMap that creates an AppKey so you can access their REST API.

  1. Sign-up for a free account.

  2. Log in to your account.

  3. Create a new API Key.

    NOTE: We will use this generated API key as a parameter in the REST calls.

Create New Extension Project

NOTE: Make sure that you are in the ThingWorx Extension Perspective. To verify, you should see a plus icon:in the menu bar. If you don’t see this, you are probably in the wrong perspective. Go back to the previous step to learn how to set the perspective to ThingWorx Extension in Eclipse.

  1. Go to File->New->Project.

  2. Click ThingWorx->ThingWorx Extension Project.

  3. Click Next.

    NOTE: A New ThingWorx Extension window will appear.

  4. Enter the Project Name (for example, MyThingworxWeatherExtension).

  5. Select Gradle or Ant as your build framework.

  6. Enter the SDK location by browsing to the directory where the Extension SDK is stored.

    NOTE: The Eclipse Plugin accepts the Extension SDK version 6.6 or higher.

  7. Enter the Vendor information (for example, ThingWorx Labs).

  8. Change the default package version from 1.0.0 to support extension dependency .

    NOTE: The information from ThingWorx Extension Properties is used to populate the metadata.xml file in your project. The metadata.xml file contains information about the extension and details for the various artifacts within the extension. The information in this file is used in the import process in ThingWorx to create and initialize the entities.

  9. Select the JRE version to 1.8.

  10. Click Next then click Finish. Your newly created project is added to the Package Explorer tab.

Create New Entity

  1. Select your project and click Add to create a new entity.

    NOTE: You can also access this from the ThingWorx menu on the menu bar.

  2. Create a Thing Template for your MyThingWorxWeatherExtension Project.

    NOTE: In this guide, we are using a Template, but in a real-world scenario, you may consider using a Thing Shape to encapsulate extension functionality. By using Thing Shapes you give users of your extension the ability to easily add new functionality to existing Things. It is simple to add a new Thing Shape to an existing Thing Template, while using the properties or services defined by a Thing Template would require recreating all existing assets using the new Template. Since subscriptions cannot be created on Thing Shapes, you might choose to create Thing Templates that implement one or more subscriptions for convenience.

  3. In the pop-up window, browse to add the source folder of your project in Source Folder.

    NOTE: It should default to the src directory of your project. In our case it will be MyThingworxWeatherExtension/src.

  4. Browse to add the package where you want to create this new class, or simply give it a name (such as com.thingworx.weather).

  5. Enter a name and description to your Thing Template (WeatherThingTemplate).

    NOTE: By default, the Base Thing Template is set to GenericThing.

  6. Select Next.

    NOTE: If you want to give other users of this entity permission to edit it in ThingWorx Composer, select the entity as an editable entity. Only non-editable entities can be upgraded in place; editable entities must be deleted and recreated when your extension is updated. If you need to make it possible to customize the extension, consider using a configuration table to save user customizations.

  7. Select Finish.

  8. Verify that you have a WeatherThingTemplate class created that extends the Thing class.

    @ThingworxBaseTemplateDefinition(name = "GenericThing")
    public class WeatherThingTemplate extends Thing {
    
         public WeatherThingTemplate() {
             // TODO Auto-generated constructor stub
         }
    }
    
  9. You might see a warning to add a serial version. You can add a default or generated serial value.

Step 5: Add Properties

In this section, you are going to add CurrentCity, Temperature and WeatherDescription properties to the WeatherThingTemplate. These properties are associated with the Thing Template and add the @ThingworxPropertyDefinitions annotation before the class definition in the code.

  1. Right click inside the WeatherThingTemplate class or right click on the WeatherThingTemplate class from the Package Explorer.

  2. Select ThingWorx Source-> Add Property.

  1. In the popup window, create a property to store the city name.

    • Name = CurrentCity, Base Type = STRING, Description = ‘’

    • Select the Has Default Value checkbox and enter a city name (eg. Boston). This will be the default value unless a specific value is passed.

    • Select the “Persistent” checkbox. This will maintain the property value if a system restart occurs. NOTE: If you select the Logged checkbox, the property value is logged to a data store. If you select the Read Only checkbox, the data will be static.

    • Select VALUE from the Data Change Type drop down menu.

      NOTE: This allows any Thing in the system to subscribe to a data change event for this property.

  2. Choose to use one of the following Data Change Types:

    Data Change TypeDescription
    AlwaysFires the event to subscribers for any property value change
    NeverDoes not fire a change event
    OnFor most values, any change will trigger this.
    OffFires the event if the new value is false
    ValueFor numbers, if the new value has changed by more than the threshold value, fire the change event. For non-numbers, this setting behaves the same as Always.
  3. Select Finish.

  4. Create another property called Temperature with a base type of NUMBER. You can keep the default values for the other parameters.

  5. Create another property called WeatherDescription with a base type of STRING. Keep the default values for the other parameters.

Step 6: Create Configuration Table

In this part of the lesson, we will create a configuration table to store the API Id that you generated from the openMapsWeather. Configuration tables are used for Thing Templates to store values similar to properties that do not change often.

  1. Right-click inside the WeatherThingTemplate class and select ThingWorx Source->Add Configuration Table.

  2. Create a new configuration table with name OpenWeatherMapConfigurationTable.

  3. Click Add in the Data Shape Field Definitions frame.

    NOTE: Configuration tables require fields (columns) with a defined table structure (DataShape).

  4. Enter appid as the name with a base type STRING.

  5. Select the Required checkbox.

  6. Click OK, then Finish to add the Configuration Table.

  7. To use the appid in the REST calls, you need to obtain the value from the configuration table and assign it to a field variable in the Java code. We will use the initializeThing method to obtain the appid value at runtime.

    NOTE: The initializeThing() method acts as an initialization hook for the Thing. Every time a Thing is created or modified, this method is executed and the value of appid is obtained from the configuration table and stored in a global field variable of the class. initializeThing() must call super.initializeThing() to ensure it performs initialization of the Thing.

  8. Create the initializeThing() method and field variable _appid with base type STRING anywhere in the WeatherThingTemplate class.

    private static Logger _logger = LogUtilities.getInstance().getApplicationLogger(WeatherThingTemplate.class);
    private String _appid;
    @Override
    public void initializeThing() throws Exception {
         super.initializeThing();
         _appid = (String) this.getConfigurationSetting("OpenWeatherMapConfigurationTable", "appid");
    }
    

    NOTE: In the code above we used ThingWorx LogUtilities to get a reference to the ThingWorx logging system, then assigned the reference to the variable _logger. In the steps below we will use this variable to log information. There are multiple kinds of loggers and log levels used in the ThingWorx Platform, but we recommend that you use the application or script loggers for logging anything from inside extension services. If prompted to import the logger, use slf4j.

Step 7: Add JAR Resources

You can add external JARs for use by your extension. Every third-party JAR that is not already included in either the ThingWorx Extension SDK or ThingWorx Core needs to be added to your extension project as a JAR Resource. These JAR resources are added to your metadata.xml as a tag and are used to reference the Java classes in the third-party JAR on which the extension depends. You can either use the Add buttonor the ThingWorx Menu from the menu bar to add a new JAR resource. By doing so, the JAR is automatically updated in the metadata file and added to the build path.

Although ThingWorx allows developers to include jar files for third-party libraries in their code, it is recommended that you avoid adding jar files for common libraries and instead use the jar files that are included with the SDK. Adding jar files to an extension could cause conflicts with jar files already used by the ThingWorx server, either when uploading an extension, or when an extension executes. Even if your extension works today, future updates to ThingWorx may require updates to your extensions. Similarly, packaging a verison of a commonly used library may mean that a customer will not be able to use your extension together with someone else’s extension.

  1. Select the project to which you want to add the jar file to and select New Jar Resource.

  2. Open the directory in which you have stored the training files for this tutorial. Browse to the Jars directory. 3.Select the json-simple-1.1.1.jar file. Add a description and click Finish.

    NOTE: This will automatically add json-simple-1.1.1.jar to the lib folder and to your project’s build path.

  3. Add httpclient-4.5.6.jar, httpcore-4.4.10.jar and commons-logging-1.2.jar directly into the twx-lib folder in the Project folder.

    NOTE: These JARs are included in the group of JARs used by ThingWorx by default.

  4. In order to build your extension locally, without bundling the jars into your extension that are available on the ThingWorx server, add the above JARs to your project’s build path by right-clicking on your project in the Package Explorer, right-click Your_Extension_Project (ie, MyThingWorxWeatherExtension) and select Build Path -> Configure Build Path. Verify the jars we added are in the build path. Otherwise, click Add JARs, then browse to the directory containing these JARs (lib) and add them.

    NOTE: twx-lib folder is a hidden folder and does not appear in the Eclipse package explorer. The twx-lib folder can be found in the WeatherExtension project inside the Eclipse workspace directory.

Step 8: Create Services

Now that you have created properties, configuration tables and added the required jars, you can begin to add services to your WeatherThingTemplate.

In this part of the lesson, we’ll add a service, UpdateWeatherInfo that will take a City parameter and update the properties of this template using the values obtained from the openWeatherMap API.

  1. Right click inside the WeatherThingTemplate and select ThingWorx Source->Add Service.

  2. Create a new service with name UpdateWeatherInfo.

  3. Click Add in the Input Parameters frame to add City parameter with a base type STRING.

  4. Set the name and base type of the Output Parameter based on the value that you want the service to return. For simplification, assume this service returns nothing. Set the Base Type to NOTHING.

  5. Click Finish to create the service.

  6. Copy and Paste the code for UpdateWeatherInfo as specified below.

@ThingworxServiceDefinition(name = "UpdateWeatherInfo", description = "updates weather description and temperature properties", category = "", isAllowOverride = false, aspects = {
        "isAsync:false" })
@ThingworxServiceResult(name = "Result", description = "", baseType = "NOTHING")
public void UpdateWeatherInfo(
        @ThingworxServiceParameter(name = "City", description = "city name", baseType = "STRING") String City) throws Exception {
        _logger.trace("Entering Service: UpdateWeatherInfo");
        String cityProp = this.getPropertyValue("CurrentCity").getStringValue();
        if (City == null){
            City = cityProp;
        } else {
            this.setPropertyValue("CurrentCity", new StringPrimitive(City));
        }
        
        String url = "http://api.openweathermap.org/data/2.5/weather?q=" +URLEncoder.encode(City,"UTF-8") + "&appid="+ _appid+"&units=imperial";
        
        // create a http client
        HttpClient client = new DefaultHttpClient();
        
        // create a get request with the URL
        HttpGet getRequest = new HttpGet(url);
        
        // add Accept header to accept json format response
        getRequest.addHeader("Accept", "application/json");
        
        // send the get request and obtain a response
        HttpResponse response = client.execute(getRequest);
        
        // if response is successful the status code will be 200.
        if (response.getStatusLine().getStatusCode() == 200) {
            BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuilder sb = new StringBuilder();
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            JSONParser parser = new JSONParser();
            JSONObject json = (JSONObject) parser.parse(sb.toString());
            JSONArray weather = (JSONArray) json.get("weather");
            Iterator<JSONObject> it = weather.iterator();
            String description = (String) it.next().get("description");
            this.setPropertyValue("WeatherDescription", new StringPrimitive(description));
            double temp = (Double) ((JSONObject) json.get("main")).get("temp");
            this.setPropertyValue("Temperature", new NumberPrimitive(temp));

            /* fire event BadWeather */
            _logger.trace("Exiting Service: UpdateWeatherInfo");
        }
}

Troubleshooting

IssueSolution
The iterator() is undefined in JSONArrayImport only org.json.simple.*. Importing other JSON libraries can give this error.
HttpClient/HttpGet could not be resolved to a type.Make sure you have imported the jars: httpclient-4.5.2.jar, httpcore-4.4.5.jar and commons-logging-1.2.jar, json-simple-1.1.1.jar as indicated in the previous chapter. Make sure you have imported the following packages in your template by Eclipse’s quick fix feature. If not, add the code below to the very beginning of your Template file.

Your code should be similar to the following:

package com.thingworx.weather;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.Iterator;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import com.thingworx.logging.LogUtilities;
import com.thingworx.metadata.annotations.ThingworxBaseTemplateDefinition;
import com.thingworx.metadata.annotations.ThingworxConfigurationTableDefinition;
import com.thingworx.metadata.annotations.ThingworxConfigurationTableDefinitions;
import com.thingworx.metadata.annotations.ThingworxDataShapeDefinition;
import com.thingworx.metadata.annotations.ThingworxFieldDefinition;
import com.thingworx.metadata.annotations.ThingworxPropertyDefinition;
import com.thingworx.metadata.annotations.ThingworxPropertyDefinitions;
import com.thingworx.metadata.annotations.ThingworxServiceDefinition;
import com.thingworx.metadata.annotations.ThingworxServiceParameter;
import com.thingworx.metadata.annotations.ThingworxServiceResult;
import com.thingworx.things.Thing;
import com.thingworx.types.primitives.NumberPrimitive;
import com.thingworx.types.primitives.StringPrimitive;
@ThingworxBaseTemplateDefinition(name = "GenericThing")
@ThingworxPropertyDefinitions(properties = {
 @ThingworxPropertyDefinition(name = "CurrentCity", description = "", category = "", baseType = "STRING", isLocalOnly = false, aspects = {
 "defaultValue:Boston", "isPersistent:true", "isLogged:true", "dataChangeType:VALUE" }), @ThingworxPropertyDefinition(name = "Temperature", description = "", category = "", baseType = "NUMBER", isLocalOnly = false, aspects = {
 "defaultValue:0", "isPersistent:true", "isLogged:true", "dataChangeType:VALUE" }), @ThingworxPropertyDefinition(name = "WeatherDescription", description = "", category = "", baseType = "STRING", isLocalOnly = false, aspects = {
 "dataChangeType:VALUE" }) })
@ThingworxConfigurationTableDefinitions(tables = {
 @ThingworxConfigurationTableDefinition(name = "OpenWeatherMapConfigurationTable", description = "", isMultiRow = false, ordinal = 0, dataShape = @ThingworxDataShapeDefinition(fields = {
 @ThingworxFieldDefinition(name = "appid", description = "", baseType = "STRING", ordinal = 0, aspects = {
 "isRequired:true" }) })) })
public class WeatherThingTemplate extends Thing {
 private static final long serialVersionUID = -5294151832877452442L;
 public WeatherThingTemplate() {}
 private static Logger _logger = LogUtilities.getInstance().getApplicationLogger(WeatherThingTemplate.class);
 private String _appid;
 @Override
 public void initializeThing() throws Exception {
     super.initializeThing();
     _appid = (String) this.getConfigurationSetting("OpenWeatherMapConfigurationTable", "appid");
 }
 @ThingworxServiceDefinition(name = "UpdateWeatherInfo", description = "updates weather description and temperature properties", category = "", isAllowOverride = false, aspects = {
    "isAsync:false" })
 @ThingworxServiceResult(name = "Result", description = "", baseType = "NOTHING")
 public void UpdateWeatherInfo(
     @ThingworxServiceParameter(name = "City", description = "city name", baseType = "STRING") String City) throws Exception {
     _logger.trace("Entering Service: UpdateWeatherInfo");
     String cityProp = this.getPropertyValue("CurrentCity").getStringValue();
     if (City == null){
         City = cityProp;
     } else {
         this.setPropertyValue("CurrentCity", new StringPrimitive(City));
     }

     String url = "http://api.openweathermap.org/data/2.5/weather?q=" +URLEncoder.encode(City,"UTF-8") + "&appid="+ _appid+"&units=imperial";

     // create a http client
     HttpClient client = HttpClientBuilder.create().build();

     // create a get request with the URL
     HttpGet request = new HttpGet(url);

     // add Accept header to accept json format response
     request.addHeader("Accept", "application/json");

     // send the get request and obtain a response
     HttpResponse response = client.execute(request);

     // if response is successful the status code will be 200.
     if (response.getStatusLine().getStatusCode() == 200) {
         BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
         StringBuilder sb = new StringBuilder();
         String line = "";
         while ((line = br.readLine()) != null) {
             sb.append(line);
         }
         JSONParser parser = new JSONParser();
         JSONObject json = (JSONObject) parser.parse(sb.toString());
         JSONArray weather = (JSONArray) json.get("weather");
         Iterator<JSONObject> it = weather.iterator();
         String description = (String) it.next().get("description");
         this.setPropertyValue("WeatherDescription", new StringPrimitive(description));
         Double temp = (Double) ((JSONObject) json.get("main")).get("temp");
         Number number = (Number) temp;
         this.setPropertyValue("Temperature", new NumberPrimitive(number));
         _logger.trace("Exiting Service: UpdateWeatherInfo");
     }
 }
}

Step 9: Create Event and Subscription

In this section, you will create a mechanism to notify the user when inclement weather occurs. For example, whenever the weather indicates storm/snow/rain, an Event should be triggered. This event is then handled by a service called a Subscription.

For this tutorial, while updating weather information inside the service UpdateWeatherInfo,we need to fire an Event: BadWeather when the weather description indicates either storm/snow/rain. This Event is handled by a Subscription: HandleWeather, which is a service that gets called whenever the BadWeather Event is fired. The subscription service HandleWeather updates a property called AlertNotification.

Create Event

In this part of the lesson, we will create an Event: BadWeather that updates weather information inside the service UpdateWeatherInfo when the weather description indicates either storm/snow/rain.

  1. Create a property AlertNotification with a baseType STRING using the Add Property feature of the plugin we discussed before.

  2. Right click inside your java file->ThingWorx Source->Add Event.

  3. Set the name to BadWeather and set a name for the Data Shape to Weather.

    NOTE: This custom Data Shape has to be created in Composer. Importing Datashapes and other custom entities created in Composer into your extension will be discussed later in the tutorial. Our DataShape Weather includes one field called WeatherDescription with a STRING base type.

  4. Click Finish.

    NOTE: This will create annotation for your EventDefinition.

Create Subscription

In this part of the lesson, we will create a Subscription: HandleWeather, which is a service that gets called whenever the BadWeather Event is fired. The subscription service HandleWeather updates a property called AlertNotification.

  1. Right click inside your java file ->ThingWorx Source->Add Subscription

  2. Set the Event Name to BadWeather and Handler Service to HandleWeather.

    NOTE: This means that whenever the BadWeather event is fired, the HandleWeather service will be executed. Source is left blank if the event belongs to the same template.

  3. Click Finish. This creates annotation for subscription service and also creates a new service called HandleWeather.

Modify Service

In this part of the lesson, you’ll ensure that when the properties are updated, BadWeather event is triggered if the description indicates rain/snow/thunderstorm. To do this, we will modify the UpdateWeatherInfo service.

After we have called the setPropertyValue method for the properties WeatherDescription and Temperature, we can check if the weather description contains snow/rain/thunderstorm. We will create an InfoTable from the Weather Datashape. InfoTables represent data sets that take the structure of the Datashape. Each row of an InfoTable can be passed as a ValueCollection to hold data within the table. When an event is fired, we need to send data along with it. This data will be passed as an InfoTable and it is then handled by the Subscription handling the Event.We use a ValueCollection to add the weatherDescription to the InfoTable. Then, this InfoTable is set as the Event Data.

  1. Add the code snippet to UpdateWeatherInfo section at the end of the service after setting the properties- Temperature and WeatherDescription.

    /* fire event BadWeather */
     if (description.contains("snow") || description.contains("rain") || description.contains("thunderstorm")) {
         ValueCollection v = new ValueCollection();
         v.put("weatherDescription", new StringPrimitive(description));
         InfoTable data = InfoTableInstanceFactory.createInfoTableFromDataShape("Weather");
         data.addRow(v);
         _logger.info("Firing event");
         ThingworxEvent event = new ThingworxEvent();
         event.setEventName("BadWeather");
         event.setEventData(data);
         this.dispatchEvent(event);
     }
    
  2. Inside the HandleWeather service, set the property AlertNotification. Ensure that you have created the property AlertNotification using the eclipse plugin.

  3. Add the following code snippet to the HandleWeather service.

    @ThingworxServiceDefinition(name = "HandleWeather", description = "Subscription handler", category = "", isAllowOverride = false, aspects = {"isAsync:false"})
    public void HandleWeather(
     @ThingworxServiceParameter(name = "eventData", description = "", baseType = "INFOTABLE") InfoTable eventData,
     @ThingworxServiceParameter(name = "eventName", description = "", baseType = "STRING") String eventName,
     @ThingworxServiceParameter(name = "eventTime", description = "", baseType = "DATETIME") DateTime eventTime,
     @ThingworxServiceParameter(name = "source", description = "", baseType = "STRING") String source,
     @ThingworxServiceParameter(name = "sourceProperty", description = "", baseType = "STRING") String sourceProperty) throws Exception {
         _logger.trace("Entering Service: HandleWeather with: Source: \"\", Event: \"BadWeather\", Property: \"\"");
         this.setPropertyValue("AlertNotification", new StringPrimitive("Alert:"+eventData.getFirstRow().getStringValue("weatherDescription")));
         _logger.trace("Exiting Service: HandleWeather");
     }
    

Now we have an event BadWeather fired every time weather description indicates storm/snow/rain and it is handled by HandleWeather service that sets the AlertNotification property to the InfoTable data passed by the event.

Step 10: Add Composer Entities

In previous parts of this tutorial, we assumed we had a datashape Weather available with field weatherDescription as the Datashape of our event: BadWeather.

In this part of the lesson, we’ll create a DataShape.

  1. Go to ThingWorx Composer. Click the + button.

  2. In the dropdown, select Data Shape.

  3. Enter a name, for example: Weather.

  4. Add a Field Definition weatherDescription with baseType STRING.

  5. Click check mark in the top left, then Save.

  6. Click the More drop-down, then click Export. Export the DataShape entity from Composer, it will download in your system as an xml file.

  7. Go back to Eclipse, right-click on your project ->Import…->ThingWorx->Entities.

  8. Click Next. Browse to the directory where the xml file was downloaded. Select the xml file and Click Finish.

    NOTE: This adds the xml file to the Entities folder in your project.

  9. Following the same procedure, import other entities required for this Extension stored in the Entities folder of the download we provided for this training.

    NOTE: You can uncheck the box for importing DataShapes_Weather.xml, if you already loaded your Datashape in the previous steps.

Step 11: Build Extension

You can use either Gradle or Ant to build your ThingWorx Extension Project. Ant is the preferred method.

Build Extension with Gradle

  1. Right click on your project ->Gradle (STS)->Tasks Quick Launcher.

NOTE: This opens up a new window.

  1. Set Project from the drop-down menu to your project name and type Tasks as build.
  2. Press Enter.

NOTE: This will build the project and any error will be indicated in the console window.

  1. Your console window will display BUILD SUCCESSFUL. This means that your extension is created and stored as a zip file in your_project->build->distributions folder.

Build Extension with Ant

  1. Go to the Package explorer -> your_project->.

  2. Right click on build-extension.xml->Run As->Ant Build.

  3. Your console output will indicate BUILD SUCCESSFUL.

NOTE: This will build your project and create the extension zip in the your_project->build->distributions folder of your project.

Step 12: Import Extension

If you have valuable data on your ThingWorx server, save the current state before importing an untested extension by duplicating and renaming the ThingworxStorage directory. This will save all current entities and a new, empty ThingworxStorage directory will be generated when Tomcat is restarted. To restore your saved state, rename the duplicate directory back to ThingworxStorage. Alternatively, If you do not back up your storage, make sure that any entities you want to save are exported into xml format. This way you will be able to restore your ThingWorx server to its initial state by deleting the storage directory before importing the saved entities.

Import Extension

  1. In the lower left corner, click Import/Export, then select Import.

NOTE: The build produces a zip file in ProjectName->build->distributions folder. This zip file will be required for importing the extension.

  1. For the Import Option option, select Extension.

  1. Click Browse and choose the zip file in the distributions folder (located in the Exclipse Project’s build directory). Click Import.

Create a Thing

  1. Create a Thing using the ThingWorx Composer with the Thing Template set to the WeatherThingTemplate.

  2. Open the ConfigurationTable tab and add the appid from the OpenWeatherMap.org site.

  3. Open the WeatherAppMashup Mashup by searching for WeatherAppMashup in the Search bar.

  1. Click View Mashup in the WeatherAppMashup Mashup window.

  2. Type the name of a city (eg. Boston) and click go.

NOTE: You can now see the current temperature reading and weather description of your city in the Mashup.

Troubleshooting

If your import did not get through with the two green checks, you may want to modify your metadata.xml or java code to fix it depending on the error shown in the logs.

IssueSolution
JAR Conflict arises between two similar jarsJAR conflicts arise when a similar jar is already present in the Composer database. Try to remove the respective jar resources from the metadata.xml. Add these jars explicitly in twx-lib folder in the project folder inside the workspace directory. Now, build the project and import the extension in ThingWorx Composer once again.
JAR is missingAdd the respective jar resource in metadata.xml using the ThingWorx->New Jar Resource. Now, build the project and import the extension in ThingWorx Composer once again.
Minimum Thingworx Version [ 7.2.1] requirements are not met because current version is: 7.1.3The version of SDK you have used to build your extension is higher than the version of the ThingWorx Composer you are testing against. You can manually edit the configfiles->metadata.xml file to change the Minimum ThingWorx version to your ThingWorx Composer version.

Step 13: Next Steps

Congratulations! You’ve successfully completed the Create an Extension tutorial, and learned how to:

  • Install the Eclipse Plugin and Extension SDK
  • Create and configure an Extension project
  • Create Services, Events and Subscriptions
  • Add Composer entities
  • Build and import an Extension

Learn More

We recommend the following resources to continue your learning experience:

CapabilityGuide
BuildApplication Development Tips & Tricks

Additional Resources

If you have questions, issues, or need additional information, refer to:

ResourceLink
CommunityDeveloper Community Forum
SupportExtension Development Guide
MarketplaceExtension Library

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290953.html

標籤:其他

上一篇:計算機科班生學計算機組成原理的意義何在呢?

下一篇:ESP8266-01S使用教程

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more