Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X
Hi, I set up a workflow to gather some data from Windchill PLM. Among these data, it will be the model pvz source for Vuforia Studio experience.
So, I want to trigger a thingworx flow that could update some source data (including the pvz file in the repository connected to the experience) before the model loading. In this way, the shown model can be the last possible version available on the thingworx repository, and consequently on windchill.
Is this possible? How to?
many thanks.
Solved! Go to Solution.
Finally worked!!!!
i set the converted file in this way
let converted_file = 'data:image/pvz;base64,' + args.data[0].Content
and deleting "&colon" and adding the symbol " : "
Now I'm curious to know why it worked in this way 😄
will u please elaborate more ?....what exactly you want to achieve?
From windchill, I want to pull some data to the thingworx repository. I know that this is feasible with thingworx flow. Among these data, there is the pvz graphic source for the vuforia experience. I want to trigger the thingworx flow from inside the vuforia experience so that I can update the source files in the thingworx repository (from which the experience takes data) before the model loads. in this way, the loaded model will be built with the last updated version of the pvz file available in the twx repo.
I hope I clarified the use case requirements. many thanks
i really dont know, how the pvz file in vuforia studio automaticatically update from thingworx repository. because as far as i know pvz file is view file once its created. how it will change automatically unless n untill you manually save n upload on thingwox and same for vuforia studio as well. i feels its not possible with above reasons, but latest updates on these softwares i m not aware about.
thanks.
Hi @GianVal ,
so far I understand your scenario here :
- you start a project - so it will loasd the start view - let say Home.js /view name here is not relevant
- now you want to update the model which is displayid in a model widget possibly by new model which was updated in the repository. So means the pvz model file in the repository was in the meantime updated . Therefore this model should be downloaded on runtime and displayed in the modelwidget instead of the old model version.
Is that scenario what you want to implment?
Here I wnat to show one possible option:
-you can use a static model -pvz - just for the case that on you mobile device the connection to TWX is not working.
- add the LoadBinary service to the Studio External Data sectionsfrom the repository thing where the CAD models are saved
- In the start.js /e.g. Home.js define the trigger for the LoadBinary servce complete event- some code like this:
//====================================================================
//this is called when loaded $scope.SaveBinJsonToTwxRepository --> $scope.GetBinJsonFromTwxRepository
$scope.$root.$on('LoadBinary-complete', function(event, args) {
console.log("LoadBinary-complete event"); //some logs
console.log("name="+event.name) //some logs
console.warn(args.data[0].Content);//some logs
//convert the format from laoded data to resource property /src
let converted_file= 'data:image/pvz;base64,'+args.data[0].Content
console.warn(converted_file) //some log printed
//add now the loaded pvz data from repository to src modelWidget
$scope.setWidgetProp('model-2','src',converted_file); $scope.$applyAsync();
});
//////
//call the server
$scope.app.apprunMyTWXService= function(pars)
{
var TWXmodelID = 'CADtestRepository'
var serviceName='LoadBinary'
var parameters = pars
twx.app.fn.triggerDataService(TWXmodelID,serviceName, parameters);
}
//////////////////////////////////////////////////////////////
$scope.GetBinJsonFromTwxRepository = function(path) {
$scope.$applyAsync(function() {
console.log("calling GetBinJsonFromTwxRepository")
$scope.app.apprunMyTWXService( {"path": path} );} ,500 );
//sample below how the rest API link should looks like
//'https://pp-5555555559fd.portal.ptc.io/Thingworx/FileRepositories/CADtestRepository/test/blue_pump.pvz'
};
- call the Thingworx service on model load or when the loading of all widget are completely e..g on after view enter event:
$scope.$on('$ionicView.afterEnter', function() {
GetBinJsonFromTwxRepository('/test/robot_test.pvz');
});
//will load the current versionof robot_test.pvz from repository
- I tested this configuration and I was able to verify that this will work in preview mode and on mobile (tested with ios i-pad 6 generation) - ok the requirment is that your TWX permissions are propperly set according to http://support.ptc.com/help/vuforia/studio/en/#page/Studio_Help_Center%2FGrantUserPermissions.html and http://support.ptc.com/help/vuforia/studio/en/#page/Studio_Help_Center%2FAnonymousAccess.html%23 on the TWX server and also added the CADtestRepository for the service LoadBinary -visibility and service runtime execute permissions for the es-public-access-org
So here sample of the test - here is TWX service called by clicking on button on runtime in preview mode
-In case that you want also call a service what will start the update proccess form Flow to repository - this could be done also be TWX service using the same mechnism as described here, but here possibly for the correct service you can post a quesiton in the TWX development community - some thing like:
How to update a repository pvz model via TWX service from Windchill Thingworx Flow ... etc.
because this is some problem which more related to TWX dev group. Thanks.
I'm trying this solution, but something doesn't work. I set up the load binary service from VF studio.
my repository is called ARepo and i changed the related parameters in your code. Can you find some mistakes?
$scope.$root.$on('LoadBinary-complete', function(event, args) {
console.log("LoadBinary-complete event");
console.log("name=" + event.name)
console.warn(args.data[0].Content);
let converted_file = 'data:image/pvz;base64,' + args.data[0].Content
console.warn(converted_file)
$scope.setWidgetProp('model-1', 'src', converted_file);
$scope.$applyAsync();
});
//////
$scope.app.apprunMyTWXService = function(pars) {
var TWXmodelID = 'ARepo'
var serviceName = 'LoadBinary'
var parameters = pars
twx.app.fn.triggerDataService(TWXmodelID, serviceName, parameters);
}
//////////////////////////////////////////////////////////////
$scope.GetBinJsonFromTwxRepository = function(path) {
$scope.$applyAsync(function() {
console.log("calling GetBinJsonFromTwxRepository")
$scope.app.apprunMyTWXService({ "path": path });
}, 500);
};
$scope.$on('$ionicView.afterEnter', function() {
$scope.GetBinJsonFromTwxRepository('resource.pvz');
});
the complete path of the resource is
"/Thingworx/FileRepositories/ARepo/resource.pvz"
The log says
"twx-entity sent but no data for twx-entity has been set yet"
many thanks
Hi @GianVal ,
for example if you look in the report e.g. in Thingworx you will see (as mentioned in your comment) here example for my environment :
/Thingworx/FileRepositories/CADtestRepository/test/blue_pump.pvz'
/Thingworx/FileRepositories/CADtestRepository/test/Illustrate-Annot_Brake-Explode.pvz
but if you click for example the link in the TWX UI it will also contain the TWX server - and should be :
https://pp-XXXXXXXXXXX.portal.ptc.io/Thingworx/FileRepositories/CADtestRepository/test/blue_pump.pvz'
https://pp-XXXXXXXXXX.portal.ptc.io/Thingworx/FileRepositories/CADtestRepository/test/Illustrate-Annot_Brake-Explode.pvz
where https://pp-XXXXXXXXXXX.portal.ptc.io is here my TWX server (ok some letter replaced by XXXX)
So means that you link requires also the Server URL s.e. https://yourServerURL//Thingworx/FileRepositories/ARepo/resource.pvz
You can see this url when you go to the service in your repository thing (GetFileListingWithLinks) and execute this service for particular folder. Then click on link and see the value in the browser
ok thanks, so..where i have to put the entire link? Here?
$scope.$on('$ionicView.afterEnter', function() {
$scope.GetBinJsonFromTwxRepository('https://THE LINK HERE?.pvz');
});
I tried but no result.
my code what I verified that it worked is something like:
//////////////////////////////////////////////////////////////
$scope.GetBinJsonFromTwxRepository = function(path) {
$scope.$applyAsync(function() {
$scope.app.apprunMyTWXService( {"path": path} );} ,500 );
};
and I called it in button
GetBinJsonFromTwxRepository('/test/robot_test.pvz');
so means my previous statement was wrong! I am sorry. This full link with server is the link what the GetFileListingWithLinks will return. This syntax is required when we try to set the source directly e.g. binding between service all time and src of the modelWidget - but here is not used! In the JavaCode example the path argument in the LoadBinary service is called on the correct Thing and therefore It do not need the full URL but only should use the relative folder location to the Thing . So in your case I will suggest
'/ARepo/resource.pvz'
/ARepo - the folder in the your repository Thing
I found a way to make it work. was an "async" js problem. anyway I can view the binary text the same as yours but I'm getting this error
"Error setting model URL on [model-1] due to [{}]"
Hi @GianVal ,
I do not know this error- so believe possibly some syntax in the generated string. Does this issue occur on mobile device or also in preview mode?
I checked the project and used following code - simplified version:
//////////////////////////////////////////////////////////////
$scope.LoadBinaryFileFromTwxRepository = function(path) {
console.log("calling LoadFileFromTwxRepository")
var TWXmodelID = 'CADtestRepository'; //this the FileRepository Thing
var serviceName = 'LoadBinary'; // this is the service name
var parameters = {"path":path} ; // this is the parameters Json
//TWX parameter name + parameter value
twx.app.fn.triggerDataService(TWXmodelID,serviceName, parameters);
$scope.$applyAsync();
};
alternative is here another version using the broatcast method and Thing name - here "CADtestRepository" is the name of the repository thing which contains the pvz files. Here in the example I have a folder /test where I uploaded the pvz file. - Used the TWX upload widget
//////////////////////////////////////////////////////////////
$scope.LoadFileFromTwxRepositoryBC = function(path) {
$scope.$applyAsync(function() {
$rootScope.$broadcast('app.mdl.CADtestRepository.svc.LoadBinary',
{"path":path}
);} ,500 );
};
it is important that the Thing e.g. (CADtestRepoistory) is added on the right side in External data section. Also the service LoadBinary should be added to External Data section:
$scope.LoadFileFromTwxRepository('/test/robot_test.pvz');
//or
$scope.LoadFileFromTwxRepositoryBC('/test/robot_test.pvz');
//======================================================
$scope.$root.$on('LoadBinary-complete', function(event, args) {
console.log("LoadBinary-complete event");
console.log("name="+event.name)
let modelWidgetName='model-1'
let converted_file= 'data:image/pvz;base64,'+args.data[0].Content
console.warn(converted_file) // here if you want to check the content to print
$scope.setWidgetProp(modelWidgetName,'src',converted_file); $scope.$applyAsync();
});
//////////////////////////////////////////////////////////////
I perfectly understood the functions' purpose and tried with the second "broadcast" method, but the same result.
I do not know.
Thank you
@GianVal , yes seems that there is an issue which I need to check more detailed , respectively to discuss with dev team. I found that on some location it will not work. On my preview installation it works but fine but on others will not - different ES and windows machine. So need to verify what is the difference. Possible there is some encode and blob convert. required .. need to check it more detailed next week . I will provide a feedback when I find the root cause.
Finally worked!!!!
i set the converted file in this way
let converted_file = 'data:image/pvz;base64,' + args.data[0].Content
and deleting "&colon" and adding the symbol " : "
Now I'm curious to know why it worked in this way 😄
Yes the syntax was a little incorrect! I checked older code and found that I used this syntax for json but it seems not to be much sensitive and was working with this error- no issue. So, it seems that PVZ format have an issue.
I found that when I generate the svg format dynamically, it required the correct syntax and otherwise it will not work. So found following code:
scope.svg_ret1 = function(imgWidget, height,color1,color2,color3,width1,width2,width3) {
var txtL=""
var width=(width1+width2+width3)
var xmlsrc='<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'
xmlsrc=xmlsrc+'<svg xmlns="http://www.w3.org/2000/svg" height="'+height+'" width="'+ width+'">\n'
xmlsrc=xmlsrc+'<rect x="0" y="0" width="'+width1+'" height="'+height+'" style="fill:'+color1+'"/>\n'
var x= width1
xmlsrc=xmlsrc+'<rect x="'+x+'" y="0" width="'+width2+'" height="'+height+'" style="fill:'+color2+'"/>\n'
x= width1+width2
xmlsrc=xmlsrc+'<rect x="'+x+'" y="0" width="'+width3+'" height="' +height+'" style="fill:'+color3+'"/>\n'
xmlsrc=xmlsrc+'</svg>'
console.log('here $scope.view.wdg['+imgWidget+'].src=')
console.warn('data:image/svg+xml;base64,'+xmlsrc)
$scope.view.wdg[imgWidget].imgsrc='data:' +'image/svg+xml;base64,'+btoa(xmlsrc);
}
the code above will generate a SVG graphic file dynamically and then it will convert it to base64 format. Here we can see the exact syntax -
let convert= "data:" +"image/ "+<type>+";base64," +btoa(xmlText);
the SVG file is first created to xml (ansi text) and then via btoa will converted to base64 format.
In case that file is obtained via request - here the service call - and the listener callback for the service complete event - the data is received already in base64 format. The text prefix is only required so that the property will "know" that the value is set to base64 / other option is to use the download link (asci text)
I belive the error with the syntax is comming from sum publi
shing to html where it was automaticaly converted by editor... here I am wrorte in this editor data: but it make automaticaly data@colon&; --- not idea how to post the correct .... so that issue was caused by some automatic syntax