HTTP Methods
Overview​
Web services calls typically require some protocol to make requests. HTTP is an incredibly common protocol, so this page will introduce how to incorporate these calls in a python script. Note that all of the examples on this page can be easily called with the Script Console, but can be utilized through some other means (the actionPerformed event on a Button).
Finding an Endpoint​
Ignition doesn't natively expose an endpoint for web services calls, so we'll have to utilize a service of some sort for the examples on this page. Fortunately, there are many public services we can utilize, such as OpenWeather. From here, we can generate an endpoint to use. At the time of this writing, we're using the following endpoint URL template:
https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}
The following table describes the various parameters in the endpoint URL:
Parameter Key | Description |
---|---|
lat, lon | Geographical coordinates (latitude, lognitude). |
appid | Your unique API key. Note: The code snippets on this page use "Your API key" as a placeholder for unique API keys. You will need to substitute the placeholder with your own API key for the code snippets to function as expected. |
The following code snippets are using the geographical coordinates for the Inductive Automation corporate headquarters located in Folsom, CA.
Making the Call​
To retrieve the results of this information in Ignition, we can use system.net.httpClient() to fetch the results of this call. We can try the following script in the Scripting Console:
#Set the endpoint URL
url = "https://api.openweathermap.org/data/2.5/weather"
#Declare a variable for system function we are using
myClient = system.net.httpClient()
#Declare a variable and set the parameters for the endpoint URL
#Instead of specifying the API call parameters for the endpoint URL in the beginning
response = myClient.get(url, {"lat":38.652330, "lon":-121.189773, "appid":"Your API key"})
#Print the output
print response.getText()
Printing this results in the following Python string:
{"coord":{"lon":-121.1898,"lat":38.6523},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"base":"stations","main":{"temp":310.34,"feels_like":310.11,"temp_min":308.88,"temp_max":312.74,"pressure":1013,"humidity":26},"visibility":10000,"wind":{"speed":4.12,"deg":290},"clouds":{"all":0},"dt":1654893775,"sys":{"type":2,"id":2006213,"country":"US","sunrise":1654864794,"sunset":1654918128},"timezone":-25200,"id":5349705,"name":"Folsom","cod":200}
Parsing the Results​
If we wanted to extract a single value ouf of the results, we have a number of approaches. One useful approach would be to turn this JSON string into a Python Dictionary. This way we can single out a key instead of using regex or looking for substrings (both valid approaches in their own regard).
When presented with a JSON string, we can call system.util.jsonDecode() to turn a JSON string into a native Python Object. Thus, we can modify our code to the following:
#Set the endpoint URL
url = "https://api.openweathermap.org/data/2.5/weather"
#Declare a variable for system function we are using
myClient = system.net.httpClient()
#Declare a variable and set the parameters for the endpoint URL
response = myClient.get(url, {"lat":38.652330, "lon":-121.189773, "appid":"Your API key"})
#Set a variable for the contents of the API call
results = response.getText()
# Convert the JSON string into a Python object. In this case, it results in a Dictionary.
decodedDict = system.util.jsonDecode(results)
# Now we can treat the results like a nested dictionary, thus we can specify the "weather" key,
# and then the nested "description" key to return a description of the current weather conditions.
# "[0]" is needed to specify the index of the list before specifying the "description" key.
print decodedDict.get("weather")[0].get("description")
Now we can easily retrieve a single value by specifying key names on the results. Printing this results in the following Python string (at the current time):
clear sky
Make the Results Human Readable​
Now that we know how to extract the results, we should clean up the output of the GET call. The JSON string returned by the endpoint could potentially be long and cumbersome to read through for a human, but we can use Python's built-in pprint library to pretty print the results.
# Import the pprint library
import pprint
# We'll instantiate an instance of PrettyPrinter, and store it in a variable named pp.
pp = pprint.PrettyPrinter(indent=4)
#Set the endpoint URL
url = "https://api.openweathermap.org/data/2.5/weather"
#Declare a variable for system function we are using
myClient = system.net.httpClient()
#Declare a variable and set the parameters for the endpoint URL
response = myClient.get(url, {"lat":38.652330, "lon":-121.189773, "appid":"Your API key"})
#Set a variable for the contents of the API call
results = response.getText()
# Convert the JSON string into a Python object. In this case, it results in a Dictionary.
decodedDict = system.util.jsonDecode(results)
# Print out the dictionary in an easy to read format.
print pp.pprint(decodedDict)
The resulting output, which is much easier to read, looks like the following:
{ u'base': 'stations',
u'clouds': { u'all': 0},
u'cod': 200,
u'coord': { u'lat': 38.6523, u'lon': -121.1898},
u'dt': 1654896566,
u'id': 5349705,
u'main': { u'feels_like': 310.59,
u'humidity': 25,
u'pressure': 1013,
u'temp': 310.84,
u'temp_max': 313.46,
u'temp_min': 309.19},
u'name': 'Folsom',
u'sys': { u'country': 'US',
u'id': 2006213,
u'sunrise': 1654864794,
u'sunset': 1654918128,
u'type': 2},
u'timezone': -25200,
u'visibility': 10000,
u'weather': [ { u'description': 'clear sky',
u'icon': '01d',
u'id': 800,
u'main': 'Clear'}],
u'wind': { u'deg': 330, u'speed': 4.12}}
None
From here we can see all of the keys that lead to our final value:
To get to the value for the description key, we simply need to address each key along the way:
# "[0]" is needed to specify the index of the list before specifying the "description" key.
print decodedDict.get("weather")[0].get("description")
Troubleshooting HTTP Methods​
When making HTTP calls, it is helpful to be familiar with the status codes that are returned by errors. To demonstrate, we could modify an earlier example:
#Set the endpoint URL
url = "https://api.openweathermap.org/data/2.5/weather"
#Declare a variable for system function we are using
myClient = system.net.httpClient()
### Note that instead of replacing the "appid" parameter with a unique API key, we will leave it as the "Your API key" placeholder.
#Declare a variable and set the parameters for the endpoint URL
response = myClient.get(url, {"lat":38.652330, "lon":-121.189773, "appid":"Your API key"})
#Print the output
print response.getText()
This will return an error, which looks like the following:
{"cod":401, "message": "Invalid API key. Please see http://openweathermap.org/faq#error401 for more info."}
Note that HTTP response code 401, which means unauthorized, was referenced. This error code is correct because we intentionally used an incorrect API key.
HTTP Response Codes​
The World Wide Web Consortium has a page dedicated to HTTP response codes, which details all possible error codes. However, several common codes are listed below:
Response Code | Description |
---|---|
400 | Bad Request - The server could not understand the request due to malformed syntax. |
401 | Unauthorized - The request requires some sort of authentication. Potentially some user credentials or an auth token of some kind. |
403 | Forbidden - The server understood what you requested, but is intentionally refusing the request. In some cases, the error message may include a reason why the request was not fulfilled (but not always). Typically, if the server doesn't include a reason, they'll use a 404 error code instead. |
404 | Not Found - Your syntax was correct, but the server could not find the resource you were asking for. This could mean a typo, or missing portion of the URL you are using. In this case, double check the address you're specifying. Depending on the configuration, this could also mean that the server does actually have the resource you requested, but doesn't want to confirm its existence (typically due to a security policy. See error code 403 above). |