Community Tip - Visit the PTCooler (the community lounge) to get to know your fellow community members and check out some of Dale's Friday Humor posts! X
Prerequisite
Content
Building GET Request
I'll be using net/http package from Go to perform the GET request to the ThingWorx Server by importing it
import ( "net/http" )
Next, we use the NewRequest() which takes method, URL & body. Since I'm sending a GET request my method will be GET, and the URL to the ThingWorx server & no body so will leave it to nil
url := myurl req, _ := http.NewRequest("GET", url, nil)
We are ignoring the error that NewRequest is returning as its already handled within the NewRequest() for us
Use Header to add the request header to be received by the ThingWorx Server, note Header is of type map[string] []string (a key : value pair)
req.Header.Add("appKey", appkey) // passing the appkey from ThingWorx Server for authentication req.Header.Add("Accept", "application/json") // accepts json as response req.Header.Add("Cache-Control", "no-cache") // not using cache to fetch data
Now we invoke the DefaultClient to perform the request & handling the error
res, err := http.DefaultClient.Do(req) if err != nil { log.Println("Failed to get all entity list from the server", err) }
We need to close the body once we have received it and then we try to read the Body returned in our request
defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body)
Here's complete function accepting URL & Application Key as string. Notice I am starting the function name with capital which denotes that I am making this as an exported function. See Exported/Unexported Identifiers In Go for more
func GetTwxServerEntities(myurl string, appkey string) { url := myurl req, _ := http.NewRequest("GET", url, nil) req.Header.Add("appKey", appkey) req.Header.Add("Accept", "application/json") req.Header.Add("Cache-Control", "no-cache") res, err := http.DefaultClient.Do(req) if err != nil { log.Println("Failed to get all entity list from the server", err) } defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body) //fmt.Println(res) fmt.Println(string(body)) }
Building PUT Request
To send property updates to the ThingWorx Server I'll create NewReader to read the strings which is JSON in this example
payload := strings.NewReader("{\"Prop1\" : \"Demo 101\",\"Prop2\" : 1001}")
Like GET request NewRequest is invoked to perform the PUT request like so
req, _ := http.NewRequest("PUT", url, payload)
Adding the header details :
req.Header.Add("appKey", appkey) req.Header.Add("Content-Type", "application/json") req.Header.Add("Cache-Control", "no-cache")
Invoke the client to perform the request
res, err := http.DefaultClient.Do(req) if err != nil { log.Println("Failed to Put the value to the ThingWorx server", err) }
Here's the complete function which takes a URL and appKey and then updates 2 property values for a Thing on the ThingWorx Server:
e.g. myurl= http://tw831psql:8080/Thingworx/Things/RESTThing/Properties/*
func TwxPut(myurl string, appkey string) { url := myurl payload := strings.NewReader("{\"Prop1\" : \"Demo 101\",\"Prop2\" : 1001}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("appKey", appkey) req.Header.Add("Content-Type", "application/json") req.Header.Add("Cache-Control", "no-cache") res, err := http.DefaultClient.Do(req) if err != nil { log.Println("Failed to Put the value to the ThingWorx server", err) } fmt.Println(res) }
And I can now verify that the property has been updated for the Thing called RESTThing
Building POST Request
Similar to GET & PUT we have to create new Request of method POST to invoke a Service in this example, for this I have already created a service that counts up a numeric property value stored in the CountUpProp property already existing under the RESTThing entity
req, _ := http.NewRequest("POST", url, nil)
Adding the Headers to the req
req.Header.Add("appKey", appKey) req.Header.Add("Content-Type", "application/json") req.Header.Add("Cache-Control", "no-cache")
Handling response and the error in case of an issue
res, err := http.DefaultClient.Do(req) if err != nil { log.Println("Posting to Thingworx server failed with error", err) } fmt.Println(res)
Here's complete thought :
func TwxPost(myurl string, appKey string) { // e.g. http://tw831psql:8080/Thingworx/Things/RESTThing/Services/CountUpService url := myurl req, _ := http.NewRequest("POST", url, nil) req.Header.Add("appKey", appKey) req.Header.Add("Content-Type", "application/json") req.Header.Add("Cache-Control", "no-cache") res, err := http.DefaultClient.Do(req) if err != nil { log.Println("Posting to Thingworx server failed with error", err) } fmt.Println(res) }
Verifying property update after the service invoke
All the above functions now can be called for e.g. in a main()
func main() { var myurl string var appkey string // Provide URL for ThingWorx fmt.Println("Enter URL, eg. http://localhost:8080/Thingworx/Server") // accepting URL at runtime fmt.Scanln(&myurl) // Provide appKey from the ThingWorx platform fmt.Println("Enter valid ThingWorx Application Key ") // accepting appKey at runtime fmt.Scanln(&appkey) GetTwxServerEntities(myurl, appkey) TwxPut(myurl, appkey) TwxPost(myurl, appkey) }