Skip to main content
18-Opal
July 1, 2017
Question

CREOSON - Beta-3 is Available!

  • July 1, 2017
  • 18 replies
  • 10584 views

CRESON Beta-3 is Available!

 

CEOSON is OpenSource Automation for CREO Parametric using JSON Transactions!

 

The latest release of CREOSON contains some new commands for BOM Exports and Dimensions with additional commands for Feature, File and Geometry related operations in CREO Parametric.  Here is a summary of the new commands by group:

 
bom (new function family)
  • get_paths
dimension (new function family)
  • copy
  • list
  • set
  • show
  • user_select
feature
  • user_select_csys
file
  • get_length_units
  • get_mass_units
  • set_length_units
  • set_mass_units
geometry
  • get_edges
  • get_surfaces

 

The latest Pre-Packaged Distribution is located here!

 

If you have any questions, please post them here...  Bugs and Feature Requests should go to the GitHub Project

 

The Help Documentation within CREOSON contains all the updated command/function information and examples.

 

Thanks for all the great feedback!

 

 

18 replies

18-Opal
July 12, 2017

@jfojtik  mmm -- this should be a really simple thing.

 

You should just have to do a windchill set_workspace  - then a normal file open...

 

Can you post the CREOSON code transactions you are trying to execute?

 

Dave

1-Visitor
July 13, 2017

hi Dave,

 

I ran the following AHK code that has a CreoSON class with a few methods.

 

obj := new CreoSON()

obj.creoSONUrl := "http://localhost:9056/creoson"

fileFullPath := "wtws://Windchill/ZKL-VaV_Poptavky/test_prt_2.prt"

res1 := obj.connect(obj.creoSONUrl)

arr1 := Utils.ParseJson(res1)

sessionId := arr1["sessionId"]

res2 := obj.getWorkDirPath(obj.creoSONUrl, sessionId)

/*
MsgBox, % "response 1:`n" . res1 . "`n`n"
	. "response 1 converted:`n" . Utils.BuildJson(arr1) . "`n`n"
	. "sessionId: " . sessionId . "`n`n"
	. "response 2:`n" . res2
*/

res5 := obj.openFileByFullPath(obj.creoSONUrl, sessionId, fileFullPath)

MsgBox, % res5

ExitApp


;=================== classes =========================

class CreoSON {
	
	creoSONUrl := "N/A"

	connect(creoSONUrl) {
	
		reqBody =
		(LTrim Join
			{
			 "command": "connection",
			 "function": "connect"
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	getWorkDirPath(creoSONUrl, sessionId) {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "creo",
			 "function": "pwd"
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
	
	}
	
	getBOMPathsFromAsm(creoSONUrl, sessionId, asmFileName := "plate_assy.asm") {
	
		reqBody =
		(LTrim Join	
			{
			 "sessionId": "%sessionId%",
			 "command": "bom",
			 "function": "get_paths",
			 "data": {
				"file": "%asmFileName%"
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
	
	}
	
	openFileByName(creoSONUrl, sessionId, fileName := "plate_assy.asm") {
	
		reqBody =
		(LTrim Join	
			{
			 "sessionId": "%sessionId%",
			 "command": "file",
			 "function": "open",
			 "data": {
				"file": "%fileName%",
				"display": true,
				"activate": true
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}

	openFileByFullPath(creoSONUrl, sessionId, fileFullPath) {
	
		fileDir := subStr(fileFullPath, 1, inStr(fileFullPath, "/", , 0) - 1)
		fileName := subStr(fileFullPath, inStr(fileFullPath, "/", , 0) + 1, strLen(fileFullPath))

		reqBody =
		(LTrim Join	
			{
			 "sessionId": "%sessionId%",
			 "command": "file",
			 "function": "open",
			 "data": {
				"file": "%fileName%",
				"dirname": "%fileDir%",
				"display": true,
				"activate": true
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	class HTTP {

		sendPOSTHTTPReq(creoSONUrl, reqBody) {
		
			WinHTTP := ComObjCreate("WinHTTP.WinHttpRequest.5.1")
			WinHTTP.Open("POST", creoSONUrl, 0)
			WinHTTP.SetRequestHeader("Content-Type", "application/json")
			try {
				WinHTTP.Send(reqBody)
				;status := WinHTTP.Status
				response := WinHTTP.ResponseText
			} catch e {
				MsgBox, % e.message
				ExitApp
			}
			
			return response
		
		}

	}

}

; ============== libs and functions from ahk community ==================

class Utils {

	/****************************************************************************************
		Function: BuildJson(obj) 
			Builds a JSON string from an AutoHotkey object

		Parameters:
			obj - An AutoHotkey array or object, which can include nested objects.

		Remarks:
			Originally Obj2Str() by Coco,
			http://www.autohotkey.com/board/topic/93300-what-format-to-store-settings-in/page-2#entry588373
			
			Modified to use double quotes instead of single quotes and to leave numeric values
			unquoted.

		Returns:
			The JSON string
	*/
	BuildJson(obj) 
	{
		str := "" , array := true
		for k in obj {
			if (k == A_Index)
				continue
			array := false
			break
		}
		for a, b in obj
			str .= (array ? "" : """" a """: ") . (IsObject(b) ? this.BuildJson(b) : this.IsNumber(b) ? b : """" b """") . ", "	
		str := RTrim(str, " ,")
		return (array ? "[" str "]" : "{" str "}")
	}

	/****************************************************************************************
		Function: ParseJson(jsonStr)
			Converts a JSON string into an AutoHotkey object

		Parameters:
			jsonstr - the JSON string to convert

		Remarks:
			Originally by Getfree,
			http://www.autohotkey.com/board/topic/93300-what-format-to-store-settings-in/#entry588268

		Returns:
			The AutoHotkey object.
	*/
	ParseJson(jsonStr)
	{
		SC := ComObjCreate("ScriptControl") 
		SC.Language := "JScript"
		ComObjError(false)
		jsCode =
		(
		function arrangeForAhkTraversing(obj){
			if(obj instanceof Array){
				for(var i=0 ; i<obj.length ; ++i)
					obj[i] = arrangeForAhkTraversing(obj[i]) ;
				return ['array',obj] ;
			}else if(obj instanceof Object){
				var keys = [], values = [] ;
				for(var key in obj){
					keys.push(key) ;
					values.push(arrangeForAhkTraversing(obj[key])) ;
				}
				return ['object',[keys,values]] ;
			}else
				return [typeof obj,obj] ;
		}
		)
		SC.ExecuteStatement(jsCode "; obj=" jsonStr)
		return this.convertJScriptObjToAhks( SC.Eval("arrangeForAhkTraversing(obj)") )
	}

	/*!
		Function: convertJScriptObjToAhks(jsObj)
			Used by ParseJson()
	*/
	convertJScriptObjToAhks(jsObj)
	{
		if(jsObj[0]="object"){
			obj := {}, keys := jsObj[1][0], values := jsObj[1][1]
			loop % keys.length
				obj[keys[A_INDEX-1]] := this.convertJScriptObjToAhks( values[A_INDEX-1] )
			return obj
		}else if(jsObj[0]="array"){
			array := []
			loop % jsObj[1].length
				array.insert(this.convertJScriptObjToAhks( jsObj[1][A_INDEX-1] ))
			return array
		}else
			return jsObj[1]
	}

	/*!
		Function: IsNumber(Num)
			Checks if Num is a number.

		Returns:
			True if Num is a number, false if not
	*/
	IsNumber(Num)
	{
		if Num is number
			return true
		else
			return false
	}

	; ============= more functions ======================

	Array_Gui(Array, Parent="") {
		if !Parent
		{
			Gui, +HwndDefault
			Gui, New, +HwndGuiArray +LabelGuiArray +Resize
			Gui, Margin, 5, 5
			Gui, Add, TreeView, w300 h200
			
			Item := TV_Add("Array", 0, "+Expand")
			this.Array_Gui(Array, Item)
			
			Gui, Show,, GuiArray
			Gui, %Default%:Default
			
			WinWait, ahk_id%GuiArray%
			WinWaitClose, ahk_id%GuiArray%
			return
		}
		
		For Key, Value in Array
		{
			Item := TV_Add(Key, Parent)
			if (IsObject(Value))
				this.Array_Gui(Value, Item)
			else
				TV_Add(Value, Item)
		}
		return
		
		GuiArrayClose:
		Gui, Destroy
		return
		
		GuiArraySize:
		GuiControl, Move, SysTreeView321, % "w" A_GuiWidth - 10 " h" A_GuiHeight - 10
		return
	} ; by GeekDude

}

 

 

Notice the response shown from the MsgBox on line 24 on the picture bellow. In the code that is the line that says 'MsgBox, % res5',

 

creoSON-test1.png

 

Thanks.

~J

18-Opal
July 13, 2017

@James62

 

I think you need a CREOSON to do the following:

 

"windchill" "set_server"

"windchill" "authorize"

"windchill" "set_workspace"

 

THEN

 

"file" "open"

 

I think you are missing a few commands before trying to perform the operation.

 

Dave

 

1-Visitor
July 18, 2017

hi Dave,

 

Thank you for the reply. Finally had a chance to try what you proposed and it worked!

 

Solution using CreoSON and AHK follows. I added a little gui to get user credentials.

 

;Ask for user login credentials
Gui, Add, Edit, vUser x10 w180, Username
Gui, Add, Edit, vPass x10 w180 Password, Password
Gui, Add, Button, Default gSubmit x10 w180, OK
Gui, Show, , Log in
Return

GuiClose: ;User closed the window.
ExitApp

Submit:
Gui, Submit, NoHide
Gui, Destroy

obj := new CreoSON()

obj.creoSONUrl := "http://localhost:9056/creoson"

fileFullPath := "wtws://Windchill/Workspace on ZKL-VaV_Poptavky/test_prt_2.prt"

res1 := obj.connect(obj.creoSONUrl)

arr1 := Utils.ParseJson(res1)

sessionId := arr1["sessionId"]

res5 := obj.wchSetServer(obj.creoSONUrl, sessionId, "Windchill")

res6 := obj.wchAuthorize(obj.creoSONUrl, sessionId, User, Pass)

res7 := obj.wchSetWorkspace(obj.creoSONUrl, sessionId, "Workspace on ZKL-VaV_Poptavky")

res8 := obj.openFileByFullPath(obj.creoSONUrl, sessionId, fileFullPath)

MsgBox,
(LTrim
	response1:
	%res1%
	
	response5:
	%res5%
	
	response6:
	%res6%
	
	response7:
	%res7%
	
	response8:
	%res8%
	
)

ExitApp


;=================== classes =========================

class CreoSON {
	
	creoSONUrl := "N/A"

	/**
	 * connection : connect
	 */
	connect(creoSONUrl) {
	
		reqBody =
		(LTrim Join
			{
			 "command": "connection",
			 "function": "connect"
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	/**
	 * creo : pwd
	 */
	getWorkDirPath(creoSONUrl, sessionId) {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "creo",
			 "function": "pwd"
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
	
	}
	
	/**
	 * bom : get_paths
	 */
	getBOMPathsFromAsm(creoSONUrl, sessionId, asmFileName := "plate_assy.asm") {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "bom",
			 "function": "get_paths",
			 "data": {
				"file": "%asmFileName%"
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
	
	}
	
	/**
	 * file : open
	 */
	openFileByName(creoSONUrl, sessionId, fileName := "plate_assy.asm") {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "file",
			 "function": "open",
			 "data": {
				"file": "%fileName%",
				"display": true,
				"activate": true
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}

	/**
	 * file : open
	 */
	openFileByFullPath(creoSONUrl, sessionId, fileFullPath) {
	
		fileDir := subStr(fileFullPath, 1, inStr(fileFullPath, "/", , 0) - 1)
		fileName := subStr(fileFullPath, inStr(fileFullPath, "/", , 0) + 1, strLen(fileFullPath))

		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "file",
			 "function": "open",
			 "data": {
				"file": "%fileName%",
				"dirname": "%fileDir%",
				"display": true,
				"activate": true
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	/**
	 * windchill : set_server
	 */
	wchSetServer(creoSONUrl, sessionId, urlOrAlias) {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "windchill",
			 "function": "set_server",
			 "data": {
				"server_url": "%urlOrAlias%"
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	/**
	 * windchill : authorize
	 */
	wchAuthorize(creoSONUrl, sessionId, user, pass) {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "windchill",
			 "function": "authorize",
			 "data": {
				"user": "%user%",
				"password": "%pass%"
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	/**
	 * windchill : set_workspace
	 */
	wchSetWorkspace(creoSONUrl, sessionId, workspaceName) {
	
		reqBody =
		(LTrim Join
			{
			 "sessionId": "%sessionId%",
			 "command": "windchill",
			 "function": "set_workspace",
			 "data": {
				"workspace": "%workspaceName%"
			 }
			}
		)

		return this.HTTP.sendPOSTHTTPReq(creoSONUrl, reqBody)
		
	}
	
	/**
	 * Subclass
	 */
	class HTTP {

		sendPOSTHTTPReq(creoSONUrl, reqBody) {
		
			WinHTTP := ComObjCreate("WinHTTP.WinHttpRequest.5.1")
			WinHTTP.Open("POST", creoSONUrl, 0)
			WinHTTP.SetRequestHeader("Content-Type", "application/json")
			try {
				WinHTTP.Send(reqBody)
				;status := WinHTTP.Status
				response := WinHTTP.ResponseText
			} catch e {
				MsgBox, % e.message
				ExitApp
			}
			
			return response
		
		}

	}

}

; ============== libs and functions from ahk community ==================

class Utils {

	/****************************************************************************************
		Function: BuildJson(obj) 
			Builds a JSON string from an AutoHotkey object

		Parameters:
			obj - An AutoHotkey array or object, which can include nested objects.

		Remarks:
			Originally Obj2Str() by Coco,
			http://www.autohotkey.com/board/topic/93300-what-format-to-store-settings-in/page-2#entry588373
			
			Modified to use double quotes instead of single quotes and to leave numeric values
			unquoted.

		Returns:
			The JSON string
	*/
	BuildJson(obj) 
	{
		str := "" , array := true
		for k in obj {
			if (k == A_Index)
				continue
			array := false
			break
		}
		for a, b in obj
			str .= (array ? "" : """" a """: ") . (IsObject(b) ? this.BuildJson(b) : this.IsNumber(b) ? b : """" b """") . ", "	
		str := RTrim(str, " ,")
		return (array ? "[" str "]" : "{" str "}")
	}

	/****************************************************************************************
		Function: ParseJson(jsonStr)
			Converts a JSON string into an AutoHotkey object

		Parameters:
			jsonstr - the JSON string to convert

		Remarks:
			Originally by Getfree,
			http://www.autohotkey.com/board/topic/93300-what-format-to-store-settings-in/#entry588268

		Returns:
			The AutoHotkey object.
	*/
	ParseJson(jsonStr)
	{
		SC := ComObjCreate("ScriptControl") 
		SC.Language := "JScript"
		ComObjError(false)
		jsCode =
		(
		function arrangeForAhkTraversing(obj){
			if(obj instanceof Array){
				for(var i=0 ; i<obj.length ; ++i)
					obj[i] = arrangeForAhkTraversing(obj[i]) ;
				return ['array',obj] ;
			}else if(obj instanceof Object){
				var keys = [], values = [] ;
				for(var key in obj){
					keys.push(key) ;
					values.push(arrangeForAhkTraversing(obj[key])) ;
				}
				return ['object',[keys,values]] ;
			}else
				return [typeof obj,obj] ;
		}
		)
		SC.ExecuteStatement(jsCode "; obj=" jsonStr)
		return this.convertJScriptObjToAhks( SC.Eval("arrangeForAhkTraversing(obj)") )
	}

	/*!
		Function: convertJScriptObjToAhks(jsObj)
			Used by ParseJson()
	*/
	convertJScriptObjToAhks(jsObj)
	{
		if(jsObj[0]="object"){
			obj := {}, keys := jsObj[1][0], values := jsObj[1][1]
			loop % keys.length
				obj[keys[A_INDEX-1]] := this.convertJScriptObjToAhks( values[A_INDEX-1] )
			return obj
		}else if(jsObj[0]="array"){
			array := []
			loop % jsObj[1].length
				array.insert(this.convertJScriptObjToAhks( jsObj[1][A_INDEX-1] ))
			return array
		}else
			return jsObj[1]
	}

	/*!
		Function: IsNumber(Num)
			Checks if Num is a number.

		Returns:
			True if Num is a number, false if not
	*/
	IsNumber(Num)
	{
		if Num is number
			return true
		else
			return false
	}

	; ============= more functions ======================

	Array_Gui(Array, Parent="") {
		if !Parent
		{
			Gui, +HwndDefault
			Gui, New, +HwndGuiArray +LabelGuiArray +Resize
			Gui, Margin, 5, 5
			Gui, Add, TreeView, w300 h200
			
			Item := TV_Add("Array", 0, "+Expand")
			this.Array_Gui(Array, Item)
			
			Gui, Show,, GuiArray
			Gui, %Default%:Default
			
			WinWait, ahk_id%GuiArray%
			WinWaitClose, ahk_id%GuiArray%
			return
		}
		
		For Key, Value in Array
		{
			Item := TV_Add(Key, Parent)
			if (IsObject(Value))
				this.Array_Gui(Value, Item)
			else
				TV_Add(Value, Item)
		}
		return
		
		GuiArrayClose:
		Gui, Destroy
		return
		
		GuiArraySize:
		GuiControl, Move, SysTreeView321, % "w" A_GuiWidth - 10 " h" A_GuiHeight - 10
		return
	} ; by GeekDude

}

 

Responses:

creoSON-test2.png

 

Thanks

~J

18-Opal
July 18, 2017

Sweet!  Congrats on getting that to work!


Dave

1-Visitor
July 18, 2017

Thanks, Now I wish I knew how to do the Upload of all modified objects in local workspace to the server-side workspace. Seems like CreoSON can't do Upload. The rest of Windchill operations I'd be able to do using Windchill Java API.

 

~J

18-Opal
July 18, 2017

Yea - CREOSON uses JLINK for the Windchill interface - so it is quite limited in this respect.

Good luck!

Dave