Community Tip - When posting, your subject should be specific and summarize your question. Here are some additional tips on asking a great question. X
This post should provide more detailed steps additional to the posts ("How to extract the components with properties from a pvz file"[1.] and "How to use ThingView Widget from Navigate to display CAD Model/Viewables in custom mashup- Concept"[2]) for the extracting the viewables and the seqnece steps information from a .pvz / Creo Illustrate model for further usage in a thingworx service.
1.) Extracting the data from the Creo View Model ( Created from Creo Illustrate via publish to pvz functionality)
As described in [1.] we required for the extraction of information a Creo View Toolkit. A good choice will be the usage the Creo View WebGL toolkit module.
The toolkit program is called inside a html document where the javaScript Creo View WebGl Api is embedded. So, the most important logic could be called on the window load function. This code below will initialize the thingview library and will open the pvz model file (value of variable CUR_MODELPATH in the code below is set the complete model path)
...
window.onload = function() { ThingView.init("js/ptc/thingview", function() { // ThingView should only be initialised once per frame //---------------------------------- //send the modelname to server var xhr = new XMLHttpRequest(); xhr.open("POST", "RAY_LOG_FILE:", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { var json = JSON.parse(xhr.responseText); } }; //set the json modelname object var JSON_BOM_MODEL_OBJ = new Object; MODELNAME = CUR_MODELPATH.substring(CUR_MODELPATH.lastIndexOf("/") + 1) JSON_BOM_MODEL_OBJ.name = "BOMMODELNAME"; JSON_BOM_MODEL_OBJ.value = MODELNAME; xhr.send(JSON.stringify(JSON_BOM_MODEL_OBJ)) console.warn("sent BOMMODELNAME=" + MODELNAME) //finish the sending of the model_name //---------------------------------- console.log("Creo View WebGL Viewer is now initialised"); session = ThingView.CreateSession("CreoViewWebGLDiv"); //refers to the CreoViewWebGLDiv -> a div area in the html fileSource // which contains the code var xhttp = new XMLHttpRequest(); MODELNAME = CUR_MODELPATH.substring(CUR_MODELPATH.lastIndexOf("/") + 1) xhttp.open("POST", "RAY_JSON_VIEWABLE:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var js_obj = new Object; js_obj.name = "VIEWABLE"; js_obj.value = MODELNAME; var data = JSON.stringify(js_obj); xhttp.send(data); model = session.MakeModel(); ////==================LoadFromURL Callback model.LoadFromURLWithCallback(CUR_MODELPATH, true, true, false, function(success, isStructure, errorStack) { var illustrations = model.GetIllustrations(); for (var i = 0; i < illustrations.size(); i++) { console.log("Illistration name: " + illustrations.get(i).name); // seems illustrations.get(i).name == pviFile model.LoadIllustrationWithCallback(illustrations.get(i).name, function(success, pviFile, stepInfoVec) { if (success === true) { var hasAnimation = model.HasAnimation() var hasSequence = model.HasSequence() xhttp.open("POST", "RAY_JSON_VIEWABLE:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var js_obj = new Object; js_obj.name = pviFile; js_obj.value = pviFile; js_obj.type = "viewable"; js_obj.hasSequence = hasSequence; js_obj.hasAnimation = hasAnimation; var data = JSON.stringify(js_obj); xhttp.send(data); for (var ii = 0; ii < stepInfoVec.size(); ++ii) { xhttp.open("POST", "RAY_JSON_VIEWABLE_STEP:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var step_obj = new Object; console.log("step nr=" + ii); step_obj.viewablename = pviFile; step_obj.nr = ii; step_obj.name = stepInfoVec.get(ii).name; step_obj.description = stepInfoVec.get(ii).description; var data = JSON.stringify(step_obj); xhttp.send(data); //============================================= } } }) } ////============= setTimeout(function() { { xhttp.open("POST", "RAY_JSON_VIEWABLE:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var js_obj = new Object; js_obj.name = "FINISHVIEWABLES"; var data = JSON.stringify(js_obj); xhttp.send(data); } }, 10000); }); ///model load from URL funciton ///////////// }); // ThingView.init( ) }; //window onload function
The program will generate 2 different json file and will send them to the http server.
When the Creo View WegGl program is started (load the html file from the http server) - So on the server side - in the node.js console we can see the printing of the received data - example on the picture below:
The Creo View WebGl program will create on the server side 2 json files (this requires also handling of the received data on the server side as allready mention in the post [1.] )
Example for extracting of data : worldcar-brake-multi-figure.pvz
worldcar-brake-multi-figure.pvz-viewableSteplist.json
[{"viewablename":"Sequence","nr":0,"name":"Sequence","description":""},
{"viewablename":"Sequence","nr":1,"name":"Step 1","description":"Remove spring clips"},
{"viewablename":"Sequence","nr":2,"name":"Step 2","description":"Release 4 bolts"},
{"viewablename":"Sequence","nr":3,"name":"Step 3","description":"Pull apart the calipers"}]
worldcar-brake-multi-figure.pvz-viewablelist.json
[{"name":"Figure 1","value":"Figure 1","type":"viewable","hasSequence":false,"hasAnimation":false},
{"name":"Sequence","value":"Sequence","type":"viewable","hasSequence":true,"hasAnimation":false},
{"name":"Parts List","value":"Parts List","type":"viewable","hasSequence":false,"hasAnimation":false},
{"name":"Sectioning","value":"Sectioning","type":"viewable","hasSequence":false,"hasAnimation":false},
{"name":"Translation","value":"Translation","type":"viewable","hasSequence":false,"hasAnimation":false},
{"name":"Animation","value":"Animation","type":"viewable","hasSequence":false,"hasAnimation":true}]
2.) Definition of a service in Thingworx for the Sequence Step List (see also "Service for creating of Bom - and Viewable Lists from json files" [3] )
Here the first Step is to define a general service which will will convert the JSON file to an InfoTable using particular dataShape. The json file will be taken from a Repositroy repository
var params = { path: the_json_path /* STRING */ }; var Content = Things[the_Repository_Name].LoadJSON(params); var params1 = { infoTableName: undefined /* STRING */, dataShapeName: the_dataShape_name /* DATASHAPENAME */ }; // result: INFOTABLE var jsonTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params1); var result = DataShapes.ThingviewBomData.CreateValues(); for(i in Content.array){ jsonTable.AddRow(Content.array[i]); } result = jsonTable; //returns the InfoTable
The service has 3 Input parameters : the_json_path, the_dataShape_name and the_Repository_Name (all are String type)
so this service could be called for any file repository, containing any json files(it is not file specific) . Via the dataShape name we will specify the filed definitions. We need to do this for each specific json file. In this case we have first manually to create a DataShape which is compatible to the Json Object. For example when we start the service RayJsonToInfoTable:
And the dataShape what we need to define in this particular example:
For the achieving of the final goal -> the creation of the Sequence Step List. We need to create a another service where we can specify the arguments for DataShape and repository name. Example:
So the input argumets are: 1.) the path to the json file and 2.) the name of the sequence for which we want to see the steps.
I am not sure if we can omit the step , where we create a dataShape for specific json - so some kind of dynamic dataShape generation - because in such case we need only to specify the json file without manual editing opreration.
Solved! Go to Solution.
In the mean time , I found a solution how to read a JSON file and to convert it to a INFO table without explicit DataShape defintion. The service definition is similar to the described service in the post.
This service has to input arguments 1.) for the JSON file path (the location of the repository where it is saved) and 2.) for the repository name - so means we can call from any repository. The output is an INFOTable but without a DataShape defintion.
The clue in here is to define the dataShape dynamicaly when we read the json File.
So the converting process is implmented in 2 loops
->>one loop for the dataShape defintion and the second loop for the reading of the different rows. Here the JavaScript code:
//var my_data_shape= "fields_dataShape"; var params = { path:the_json_path /* STRING */ }; //create an json Object array var ContentJSON = Things[the_repository].LoadJSON(params); //get the first row for the dataShape defintion var FirstRowJson =ContentJSON.array[0]; //create an empty InfoTable var resInfoTable = { dataShape: { fieldDefinitions : {} }, rows: [] }; //defines the dataShape for(var prop in FirstRowJson) { if(FirstRowJson.hasOwnProperty(prop)) { resInfoTable.dataShape.fieldDefinitions[prop] = { name:prop, baseType: 'STRING' }; } } //add the rows to the InfoTables for(i in ContentJSON.array){ resInfoTable.rows[i]=ContentJSON.array[i]; } result = resInfoTable;
And here an example for the results of the service call:
In the mean time , I found a solution how to read a JSON file and to convert it to a INFO table without explicit DataShape defintion. The service definition is similar to the described service in the post.
This service has to input arguments 1.) for the JSON file path (the location of the repository where it is saved) and 2.) for the repository name - so means we can call from any repository. The output is an INFOTable but without a DataShape defintion.
The clue in here is to define the dataShape dynamicaly when we read the json File.
So the converting process is implmented in 2 loops
->>one loop for the dataShape defintion and the second loop for the reading of the different rows. Here the JavaScript code:
//var my_data_shape= "fields_dataShape"; var params = { path:the_json_path /* STRING */ }; //create an json Object array var ContentJSON = Things[the_repository].LoadJSON(params); //get the first row for the dataShape defintion var FirstRowJson =ContentJSON.array[0]; //create an empty InfoTable var resInfoTable = { dataShape: { fieldDefinitions : {} }, rows: [] }; //defines the dataShape for(var prop in FirstRowJson) { if(FirstRowJson.hasOwnProperty(prop)) { resInfoTable.dataShape.fieldDefinitions[prop] = { name:prop, baseType: 'STRING' }; } } //add the rows to the InfoTables for(i in ContentJSON.array){ resInfoTable.rows[i]=ContentJSON.array[i]; } result = resInfoTable;
And here an example for the results of the service call: