12 Replies Latest reply on Jan 16, 2018 4:24 PM by miikkae RSS
    miikkae Explorer

    How to remove Remote Things

    How can I remove Remote Things that are show in Monitoring -> Remote Things?

    I've been working on a service to automatically create new things based on Resources["DeviceFunctions"].GetUnboundRemoteThings() and binding them too.

    Now I have a huge amount of remote things showing in the Remote Things' Monitoring page's "All" tab (with red mark, so they are all offline). There're no actual Things for them to delete, though. That's why it's odd that they don't appear on the "Unbound" tab.

    There're no identifiers specified, so when I connect and bind those names with SDK agent, they seem like online, otherwise offline.


    If I try to create a Thing with that name, I get an error saying: save failed, status: "Conflict", message: "Object With This Name Already Exists"

    even though I can't find Thing with that name.


    It seems to have been my bad for not having the the things unbound after closing the SDK agent. Then I just deleted those things and it got somewhat messed up.

      • Re: How to remove Remote Things
        paic Collaborator

        Most likely these have become 'ghost' entities because they were incorrectly created.

        Try restarting Tomcat.

        • Re: How to remove Remote Things
          adamr Creator

          Also note when creating entities via service it is important to include proper error handling in the script.  See the following article....



            • Re: How to remove Remote Things
              miikkae Explorer

              Thanks but it seems, we don't have PTC Global Support agreement so I have no access to that article. Some error handling's already included to my service script. I'll ask if we can get that agreement.

                • Re: How to remove Remote Things
                  adamr Creator
                  • To remove existing "ghost" entities, restart Tomcat
                  • Proper error handling when creating entities programmatically will mitigate the risk of database corruption and ghost entities
                    • Use Try Catch statements to delete entities if they are not created properly
                    • Create, Enable and restart the Thing in the try Statement
                      • E.g.

                  try {

                       var params = { tags: undefined /* TAGS */,

                                           thingTemplateName: "GenericThing" /*THINGTEMPLATENAME */,

                                            description: "new thing" /* STRING */,

                                            name: thing1 /* STRING */ };

                       // no return





                  • If there is any error in Thing creation, use the catch statement to delete the entities
                    • E.g.

                  catch(e) {

                       logger.error("Unable to create Thing");

                        var params = { name: thing1 /* THINGNAME */ };

                        // no return



              • Re: How to remove Remote Things
                carlesc Heavyweight Champ

                Hi Quang-Dung,


                You can't have Ghost and Real Thing with the same name on the same system, or it's a Ghost or it's a real Thing.


                If you are asking how to know if a Thing it's a Ghost or a Real Thing, I think there isn't an answer to this.


                If you want to prevent to create an already existing thing, try to check first for it's existence.


                Don't try to do Try/Catch/Delete to an unconsistent system, first restart your system, then do it on the correct way.



                • Re: How to remove Remote Things
                  costinb Explorer

                  Hi Quang-Dung,


                  In regards to ghost entities, I would also like to share a script with you with which you can detect all ghost things in your system. It doesn't help you delete them, but you could run it in a subscription to get notified when you have any ghost entities and then immediately restart the server. The service receives as an input parameter your server name (HostURL) and an AppKey name (not the actual appKey value). It basically compares the Things in the spot light search (database) with the Things in the REST API (in memory). If there is a difference, it will print that out as an infotable (which will be the result of your service).


                  In my case the DataShape for the resulting Infotable is one specific to my project, but you can change it to include just the thingName.


                  Let me know if this helps or if you have any questions.


                  try { var params = {

                      searchExpression: "*" /* STRING */,

                      types: {"items":["Thing"]}

                      /* JSON */,

                      withPermissions: true /* BOOLEAN */,

                      aspects: {"isSystemObject":false}

                      /* JSON */,

                      searchDescriptions: true /* BOOLEAN */,

                      sortBy: "lastModifiedDate" /* STRING */,

                      isAscending: false /* BOOLEAN */,




                  // result: INFOTABLE dataShape: SpotlightSearch

                  /* controllers in spotlight search may contain entities

                     that have been created only in memory


                  var spotlightSearchItems = Resources["SearchFunctions"].SpotlightSearch(params);



                  /* the infotable below will contain ONLY things

                     that are also in the ThingWorx database


                  // result: INFOTABLE dataShape: RootEntityList



                  // result: STRING

                  var KeyID = ApplicationKeys[AppKey].GetKeyID();





                  var params = {

                    proxyScheme: undefined /* STRING */,

                    headers: undefined /* JSON */,

                    ignoreSSLErrors: undefined /* BOOLEAN */,

                    useNTLM: undefined /* BOOLEAN */,

                    workstation: undefined /* STRING */,

                    useProxy: undefined /* BOOLEAN */,

                    withCookies: undefined /* BOOLEAN */,

                    proxyHost: undefined /* STRING */,

                    url: HostURL + "/Thingworx/Things?appKey=" + KeyID/* STRING */,

                    timeout: undefined /* NUMBER */,

                    proxyPort: undefined /* INTEGER */,

                    password: undefined /* STRING */,

                    domain: undefined /* STRING */,

                    username: undefined /* STRING */




                  // result: JSON

                  //var controllers = Resources["ContentLoaderFunctions"].LoadJSON(params);





                  var entities = Resources["ContentLoaderFunctions"].LoadJSON(params);

                  var params = {

                    infoTableName : "InfoTable",

                    dataShapeName : "ControllersDisplayShape"




                  // CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(ControllersDisplayShape)

                  var thingsInfotable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);





                  for (var i = 0; i <  entities.rows.length; i++) {

                       if (entities.rows[i].isSystemObject == false)







                  var ghostsCount = thingsInfotable.getRowCount()- spotlightSearchItems.getRowCount();

                  logger.info("Number of ghosts is " + ghostsCount); 



                  // If the ghost count is zero, the result will just be an empty infotable

                  var params = {

                      infoTableName : "InfoTable",

                      dataShapeName : "ControllersDisplayShape"




                  // CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(DisplayNameDataShape)

                  var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);



                  // if the ghostCount is higher than 0, we want to check which is(are) the actual ghost controller(s)



                  if (ghostsCount > 0) {

                      for (var i = 0; i < thingsInfotable.getRowCount(); i++) {



                          for (var j = 0 ; j < spotlightSearchItems.getRowCount(); j++) {

                              if (thingsInfotable.rows[i].ControllerName == spotlightSearchItems.rows[j].name) {

                                  //we discard from the spotlight search every controller which we already found in the DB

                                  //to reduce our search time








                      // the remaining infotable will contain only the ghosts

                    var result = thingsInfotable;






                      } catch (err) {

                          logger.error ("Encountered error " + err + " at line " + err.lineNumber) ;