cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Learn all about PTC Community Badges. Engage with PTC and see how many you can earn! X

How to load JSON file from Thingworx Repository

Velkumar
19-Tanzanite

How to load JSON file from Thingworx Repository

 Hi all,

 

I have some JSON dataset in Thingworx repository. I'm looking for a way to download and use it in experience runtime. Could any one help me with this.

 

Thanks in advance.


/VR 

ACCEPTED SOLUTION

Accepted Solutions

Yes this seems to be difficult to achieve. I think in your code is a problem with passing arguments between the call of the service and the event. It is  correctly as your mentionded that this is asynchronous call – but nearly all calls in JavaScript are asynchronous calls. The $broadcast works asynchronously and will not return any values and there is no  way to pass e.g. the key argument to the event LoadJSON-complete. 

Also, I want to point that  to define the event listener inside the forEach loop is definitely not a good idea. The event listener should be defined globally.

So I fixed the code  and called the broadcast /also alternate call is twx.app.fn.triggerDataService (better) / - called the service in a loop for each key/value pair from  the json list . So all calls are executed immediately (as expected) - An then after some time the events are fired- but there seems to be something a twx srv cache  issue  - so it seems to forget the other call - when we have more than 2 or 3 call so it did not emit the events for all calls. 

To the question - how to make synchronous - I do not think that it is possible here.  In generally we can use some promise approach but here we have an array as results and it will be difficult to manage the different items

For me seems that the best approach is to use some recursive call principle - 

call - event completed - next call etc....

The following code was working fine in my example:

 

// $scope, $element, $attrs, $injector, $sce, $timeout, $http, $ionicPopup, and $ionicPopover services are available

$scope.modelDataDynamic=[];
$scope.COUNT=0;
 
var MODEL_JSON = {
  'model-1-a': 'a.json',
  'model-1-b': 'b.json',
  'model-1-c': 'c.json',
  'model-1-d': 'd.json',
  'model-1-e': 'e.json',
  'model-1-f': 'f.json',
}
//load MODEL_JSON files
console.log('load MODEL_JSON files');

//==================================================
//==================================================
angular.element(document).ready(function () {
                              console.log("Register the LoadJson-Complete");
  //==== LoadJSON COMPLETE  
  $scope.$root.$on('LoadJSON-complete', function (event, args) {
      console.log("LoadJSON-complete event");
      //will print to console the event name - LoadJSON-Complete
      console.log("name=" + event.name)
      // the data was the event returns
      $scope.modelDataDynamic[$scope.COUNT].jsonData = args.data;   
      //print to the console to check the data
      console.log(JSON.stringify($scope.modelDataDynamic[$scope.COUNT].jsonData))
    // debugging inof
      console.log("key=" +$scope.modelDataDynamic[$scope.COUNT].key+";value="
                 + $scope.modelDataDynamic[$scope.COUNT].value + ";COUNT="+$scope.COUNT+
                   "length="+$scope.modelDataDynamic.length);
      // this a double check we will convert it to string and parse it back to json
      //this will ensure that data is correct and has the correct syntax
      if( ++$scope.COUNT > $scope.modelDataDynamic.length-1)
      {//finished
         $scope.finished(); 
      }
      else
      {$timeout($scope.GetJsonFromTwxRepository('/test/jsons/'
                                                + $scope.modelDataDynamic[$scope.COUNT].value),500,true)    
      }
    });
})
//===================================================
//==================================================
$scope.GetJsonFromTwxRepository = function (path) {
  console.log("$scope.GetJsonFromTwxRepository(path="+path+") ");
 $timeout(function () {
   // $rootScope.$broadcast('app.mdl.TestRepository.svc.LoadJSON',
   twx.app.fn.triggerDataService('TestRepository','LoadJSON',
      {"path": path});}
    , 5,true);
  console.log("after call of GetJsonFromTwxRepository")
};
//==================================================
//==================================================
$scope.$on('$ionicView.afterEnter', function () {
  console.log("$ionicView.afterEnter was called ");
  console.log('Calling now the service in a loop');
$scope.COUNT=0;
  angular.forEach(MODEL_JSON, function (value, key) {
    console.log("calling angular.forEach value="+value+ " key="+key);
    let temp_obj= {}
    temp_obj.key=key
    temp_obj.value=value
    $scope.modelDataDynamic.push(temp_obj)  })
   
   $timeout(()=>{
         $scope.GetJsonFromTwxRepository('/test/jsons/' +$scope.modelDataDynamic[$scope.COUNT].value) 
         $scope.$applyAsync();
                },100,true)
})

//=======================$scope.finished();=========
//==================================================

//$scope.$watch('COUNT', function (newValue, oldValue, scope) {
 //if(scope.app.params.SVC_CALL_NUM <1)
$scope.finished=function(){ 
     
        console.warn("completed the loop");
        let a = $scope.modelDataDynamic
        for (var i in a) 
        {  console.log("here Json for  $scope.modelDataDynamic["+i+"]")
           console.log("key="+ a[i].key + " value="+a[i].value)
           console.log("==============================================")
           console.log(JSON.stringify(a[i].jsonData));
           console.log("==============================================")
   
}                                
    $timeout( function() { console.warn($scope.modelDataDynamic);}, 1000)
}

 

So when tested I was working fine with the following print:

2020-05-21_1-45-01.jpg

View solution in original post

8 REPLIES 8
sdidier
17-Peridot
(To:Velkumar)

Hello,

 

Did you have a look to this post ?

https://community.ptc.com/t5/Vuforia-Studio/How-to-load-3D-model-in-runtime-from-Thingworx-File-Repository/m-p/639914#M7233

 

I think it is a good start about how to download a file.

To read it, I think that it is possible to store json data into a variable in javascript.

 

Best regards,

Samuel

Velkumar
19-Tanzanite
(To:sdidier)

Hi @sdidier 

 

I tried method mentioned in that post but I'm not able to read json value in runtime.

 

/VR

"was not able to read at runtime" - means it works in preview but not on mobile or  both not working in preview and  not working on Mobile plattfrom?

Hi @RolandRaytchev 

 

Its not working in preview also.

 

/VR

Thanks, so  I asked this question because , when it work in preview it still could not work on mobile device - but in this case is issue based on permission setting of the used method.

 

1.)To the current issue  - let say you have a repository thing named "CAD-Files-Repository"

//////////////////////////////////////////////////////////////
$scope.GetJsonFromTwxRepository = function(path) {
 $scope.$applyAsync(function() {
   $rootScope.$broadcast('app.mdl.CAD-Files-Repository.svc.LoadJSON',
                          {"path":path}
                         );}   ,500 );
   console.log("after call of GetJsonFromTwxRepository")
};
////////////////////////////////////////////////////////////

 

Here is important the service string-  in my example it is 'app.mdl.CAD-Files-Repository.svc.LoadJSON' where the Thingworx thing 'CAD-Files-Repository' - in case that your repository is named MyRepository1 - then the string should be  'app.mdl.MyRepository1.svc.LoadJSON' . 

 

2.) another point is that you need to add the service LoadJSON of your repository thing to the External data section:

 

2020-05-19_19-48-51.jpg

 

3.) you need also to define the method which will return the results of the Json. Please, pay attention that the call of the broadcast service will start the twx service but will not return any values from it. When the twx service complete it will emit an event to trigger this event we can use some code like this:

 

$scope.$on('$ionicView.afterEnter',function(){
  console.log("$ionicView.afterEnter was called ");
 $scope.$root.$on('LoadJSON-complete', function(event, args) { 
  console.log("LoadJSON-complete event");
  //will print to console the event name - LoadJSON-Complete
   console.log("name="+event.name)
   console.warn(args.data);// the data was the event returns
   $scope.COMP_LOCs=args.data // here we will set the data to global vars
   console.log(JSON.stringify( $scope.COMP_LOCs))//print to the console to check the data
    let json_new_obj=JSON.parse(JSON.stringify( $scope.COMP_LOCs))
	// this a double check we will convert it to string and parse it back to json
	//this will ensure that data is correct and has the correct syntax
      
});

}) //event: when 2d View loaded

 

So when the event is called it will set the global variable - here $scope.COMP_LOCs which you can  use later to read the json or different subparts of it.

Hi @RolandRaytchev 

 

Thanks for the code it works fine. When I try to execute Thingworx service in a loop, output of the service is not varying/wrong. Looks like function 'GetJSONfromTWXRepository' is running in async mode. How we can make this is as synchronous one. 

 

PFB code for reference:

var MODEL_JSON = {
  'model-1-a': 'a.json',
  'model-1-b': 'b.json'
}
//load MODEL_JSON files
console.log('load MODEL_JSON files');
// $scope, $element, $attrs, $injector, $sce, $timeout, $http, $ionicPopup, and $ionicPopover services are available

$scope.GetJsonFromTwxRepository = function (path) {
  $scope.$applyAsync(function () {
    $rootScope.$broadcast('app.mdl.SystemRepository.svc.LoadJSON',
      {
        "path": path
      }
    );
  }
    , 500);
  console.log("after call of GetJsonFromTwxRepository")
};
$scope.modelDataDynamic = [];
$scope.$on('$ionicView.afterEnter', function () {
  console.log('Calling service');
  angular.forEach(MODEL_JSON, function (value, key) {
    $scope.GetJsonFromTwxRepository('/' + value);
    console.log(value);
    console.log("$ionicView.afterEnter was called ");
    $scope.$root.$on('LoadJSON-complete', function (event, args) {
      console.log("LoadJSON-complete event");
      //will print to console the event name - LoadJSON-Complete
      console.log("name=" + event.name)
      console.log(event);
      console.warn(args.data);
      // the data was the event returns
      $scope.COMP_LOCs = args.data // here we will set the data to global vars
      console.log(JSON.stringify($scope.COMP_LOCs))//print to the console to check the data
      $scope.modelDataDynamic[key] = args.data;
      // this a double check we will convert it to string and parse it back to json
      //this will ensure that data is correct and has the correct syntax
    }
    );
  
  });
}
)

console.log($scope.modelDataDynamic);

modelDataDynamic output is same for both key. How we can over come this ?

 

/VR

 

Yes this seems to be difficult to achieve. I think in your code is a problem with passing arguments between the call of the service and the event. It is  correctly as your mentionded that this is asynchronous call – but nearly all calls in JavaScript are asynchronous calls. The $broadcast works asynchronously and will not return any values and there is no  way to pass e.g. the key argument to the event LoadJSON-complete. 

Also, I want to point that  to define the event listener inside the forEach loop is definitely not a good idea. The event listener should be defined globally.

So I fixed the code  and called the broadcast /also alternate call is twx.app.fn.triggerDataService (better) / - called the service in a loop for each key/value pair from  the json list . So all calls are executed immediately (as expected) - An then after some time the events are fired- but there seems to be something a twx srv cache  issue  - so it seems to forget the other call - when we have more than 2 or 3 call so it did not emit the events for all calls. 

To the question - how to make synchronous - I do not think that it is possible here.  In generally we can use some promise approach but here we have an array as results and it will be difficult to manage the different items

For me seems that the best approach is to use some recursive call principle - 

call - event completed - next call etc....

The following code was working fine in my example:

 

// $scope, $element, $attrs, $injector, $sce, $timeout, $http, $ionicPopup, and $ionicPopover services are available

$scope.modelDataDynamic=[];
$scope.COUNT=0;
 
var MODEL_JSON = {
  'model-1-a': 'a.json',
  'model-1-b': 'b.json',
  'model-1-c': 'c.json',
  'model-1-d': 'd.json',
  'model-1-e': 'e.json',
  'model-1-f': 'f.json',
}
//load MODEL_JSON files
console.log('load MODEL_JSON files');

//==================================================
//==================================================
angular.element(document).ready(function () {
                              console.log("Register the LoadJson-Complete");
  //==== LoadJSON COMPLETE  
  $scope.$root.$on('LoadJSON-complete', function (event, args) {
      console.log("LoadJSON-complete event");
      //will print to console the event name - LoadJSON-Complete
      console.log("name=" + event.name)
      // the data was the event returns
      $scope.modelDataDynamic[$scope.COUNT].jsonData = args.data;   
      //print to the console to check the data
      console.log(JSON.stringify($scope.modelDataDynamic[$scope.COUNT].jsonData))
    // debugging inof
      console.log("key=" +$scope.modelDataDynamic[$scope.COUNT].key+";value="
                 + $scope.modelDataDynamic[$scope.COUNT].value + ";COUNT="+$scope.COUNT+
                   "length="+$scope.modelDataDynamic.length);
      // this a double check we will convert it to string and parse it back to json
      //this will ensure that data is correct and has the correct syntax
      if( ++$scope.COUNT > $scope.modelDataDynamic.length-1)
      {//finished
         $scope.finished(); 
      }
      else
      {$timeout($scope.GetJsonFromTwxRepository('/test/jsons/'
                                                + $scope.modelDataDynamic[$scope.COUNT].value),500,true)    
      }
    });
})
//===================================================
//==================================================
$scope.GetJsonFromTwxRepository = function (path) {
  console.log("$scope.GetJsonFromTwxRepository(path="+path+") ");
 $timeout(function () {
   // $rootScope.$broadcast('app.mdl.TestRepository.svc.LoadJSON',
   twx.app.fn.triggerDataService('TestRepository','LoadJSON',
      {"path": path});}
    , 5,true);
  console.log("after call of GetJsonFromTwxRepository")
};
//==================================================
//==================================================
$scope.$on('$ionicView.afterEnter', function () {
  console.log("$ionicView.afterEnter was called ");
  console.log('Calling now the service in a loop');
$scope.COUNT=0;
  angular.forEach(MODEL_JSON, function (value, key) {
    console.log("calling angular.forEach value="+value+ " key="+key);
    let temp_obj= {}
    temp_obj.key=key
    temp_obj.value=value
    $scope.modelDataDynamic.push(temp_obj)  })
   
   $timeout(()=>{
         $scope.GetJsonFromTwxRepository('/test/jsons/' +$scope.modelDataDynamic[$scope.COUNT].value) 
         $scope.$applyAsync();
                },100,true)
})

//=======================$scope.finished();=========
//==================================================

//$scope.$watch('COUNT', function (newValue, oldValue, scope) {
 //if(scope.app.params.SVC_CALL_NUM <1)
$scope.finished=function(){ 
     
        console.warn("completed the loop");
        let a = $scope.modelDataDynamic
        for (var i in a) 
        {  console.log("here Json for  $scope.modelDataDynamic["+i+"]")
           console.log("key="+ a[i].key + " value="+a[i].value)
           console.log("==============================================")
           console.log(JSON.stringify(a[i].jsonData));
           console.log("==============================================")
   
}                                
    $timeout( function() { console.warn($scope.modelDataDynamic);}, 1000)
}

 

So when tested I was working fine with the following print:

2020-05-21_1-45-01.jpg

Thank you much @RolandRaytchev . It works perfectly :).

Announcements

Top Tags