# Ignition integration with Peplink Incontrol2 API

**URL:** <https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161>\
**Category:** Ignition\
**Created:** [June 24, 2021, 3:15pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161 "2021-06-24T15:15:35Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![taupo](https://avatars.discourse-cdn.com/v4/letter/t/2bfe46/32.png) [@taupo](https://forum.inductiveautomation.com/u/taupo)\
**Post date:** [June 24, 2021, 3:15pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/1 "2021-06-24T15:15:35Z")

</div>

Hey Guys

Been playing around with Ignition for a week now and absolutely love it.  
I’m looking to integrate [API calls to Peplink’s InControl2](https://www.peplink.com/ic2-api-doc/#!)

I can get the calls working on Postman for example

PUT or DELETE  
URL - [https://api.ic.peplink.com/rest/o/{organization\_id}/g/{group\_id}/device\_tags](https://api.ic.peplink.com/rest/o/%7Borganization_id%7D/g/%7Bgroup_id%7D/device_tags)  
(Authentication token) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
(body - raw data)  
{data:  
{device\_ids:[1,10],  
tag\_names:[allowinternet]}  
}

This call allows me to add or delete a tag (not a tag in Ignition) to a device in InControl2’s management which allows for rules to be acted upon e.g. firewall rules change to allow or block internet

Could someone please explain to me how to take a functioning call in Postman and integrate it into a tag in Ignition.  
I have already tired following some examples but nothing seams to quite function.

Have a great day!

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [June 24, 2021, 3:23pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/2 "2021-06-24T15:23:19Z")

</div>

This thread should help you out  
[Connecting to Smart Home Devices - Maker - Inductive Automation Forum](http://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/16)

---

<div class="post-metadata">

**Author:** ![taupo](https://avatars.discourse-cdn.com/v4/letter/t/2bfe46/32.png) [@taupo](https://forum.inductiveautomation.com/u/taupo)\
**Post date:** [June 24, 2021, 3:37pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/3 "2021-06-24T15:37:02Z")

</div>

Awesome, that’s a great one. Will work my way through it now

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [June 24, 2021, 5:21pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/4 "2021-06-24T17:21:04Z")

</div>

I use the same method for the API helper functions I am writing for Ecobee Smart Thermostats.

---

<div class="post-metadata">

**Author:** ![taupo](https://avatars.discourse-cdn.com/v4/letter/t/2bfe46/32.png) [@taupo](https://forum.inductiveautomation.com/u/taupo)\
**Post date:** [June 25, 2021, 10:00am UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/5 "2021-06-25T10:00:46Z")

</div>

Peplink do provide a sample shell script.  
I think it needs to be completely re-written in python to work in Ignition though.

```auto
#!/bin/bash

## Sample script for making IC2 API calls
## Revision 1.3
## Last modified: 2019-06-21
## By Billy Lau, Michael Chan

#
## Please input your InControl 2 OAuth client_id, client_secret and redirect_uri below
## You can optain a set of client ID and secret from your user profile page by clicking 
## your email address on the top of the InControl 2 screen, scrolling to the "Client 
## Application" section, clicking the "New Client" button, and filling in the form.
##
## For the redirect_uri, you may fill in http://www.peplink.com in the above form
## and the redirect_uri variable below
client_id=""
client_secret=""
redirect_uri=""

# For InControl 2, the api_server_prefix is https://api.ic.peplink.com.  
# For InControl appliances, this is https://{SERVER_NAME_HERE}.
api_server_prefix="https://api.ic.peplink.com"

# For InControl 2, set 1 to verify the API service's SSL certificate.
# For InControl appliances without a valid SSL certificate, set this to 0 to ignore the certificate validity.
verify_ssl_cert=1

################# Code for OAuth2 token handling goes below ##################
access_token_file="${HOME}/.access_token"
refresh_token_file="${HOME}/.refresh_token"
tmpfile="/tmp/ic2.tmpfile.$$"
# InControl token endpoint
ic2_token_url="${api_server_prefix}/api/oauth2/token"
# InControl authorization endpoint
ic2_auth_url="${api_server_prefix}/api/oauth2/auth?client_id=${client_id}&response_type=code"

if ["${client_id}" == ""] || ["${client_secret}" == ""] || ["${redirect_uri}" == ""]; then
	echo "Please edit this script and enter Client ID and Client Secret"
	exit 1
fi

# Check if jq has been installed
if ! command -v jq > /dev/null 2>&1 ; then
	echo "Error: Missing jq command."
	echo "Run \"apt install jq\" or \"yum install jq\" to install."
	exit 2
fi

if ["$verify_ssl_cert" != "0"]; then
	curl_opt=" -k "
else
	curl_opt=""
fi

function save_tokens() {
	result=$(cat)
	local -n access_token_tmp=$1
	local -n refresh_token_tmp=$2
	access_token_tmp=`echo "${result}"|jq -r .access_token`
	refresh_token_tmp=`echo "${result}"|jq -r .refresh_token`
	expires_in=`echo "${result}"|jq -r .expires_in`
	if ["${access_token_tmp}" == ""]; then
		echo "Unable to obtain an access token. Process aborted"
		echo "Returned: $result"
		exit 3
	fi
	# Save the access token and refresh token."
	echo ${access_token_tmp} > ${access_token_file}
	echo ${refresh_token_tmp} > ${refresh_token_file}
	# Set the files' last modified date to the tokens' expiry date
	touch -d @$(( $(date +%s) + expires_in )) ${access_token_file}
	touch -d @$(( $(date +%s) + expires_in + 30*60*60 )) ${refresh_token_file}
}

# If the access token file has not expired
if [-f ${access_token_file}] && [$(stat -c %Y ${access_token_file}) -gt $(date +%s)]; then
	access_token=$(cat ${access_token_file})
# If the access token is invalid but the refresh token has not expired, acquire new access and refresh tokens
elif [-f ${refresh_token_file}] && [$(stat -c %Y ${refresh_token_file}) -gt $(date +%s)]; then
	ic2_token_params="client_id=${client_id}&client_secret=${client_secret}&grant_type=refresh_token&refresh_token=$(cat ${refresh_token_file})"
	curl $curl_opt -so $tmpfile -X POST -d "$ic2_token_params" "${ic2_token_url}"
	if ! save_tokens access_token refresh_token < $tmpfile; then
		rm -f $tmpfile
		exit 4
	fi
else
	echo ""
	echo "Start a web browser, visit the following URL and follow the instructions."
	echo ""
	echo "${ic2_auth_url}"
	echo ""
	echo "You will be redirected to $redirect_uri?code=CODE_HERE."
	echo -n "Please enter the 'code' in the redirected URL here: "
	read code

	if ["${code}" == ""]; then
		echo "Error: The code is empty. Process aborted"
		exit 5
	fi

	ic2_token_params="client_id=${client_id}&client_secret=${client_secret}&grant_type=authorization_code&code=${code}&redirect_uri=${redirect_uri}"

	## POST data to token endpoint
	curl $curl_opt -so $tmpfile --data "${ic2_token_params}" "${ic2_token_url}"
	if ! save_tokens access_token refresh_token < $tmpfile; then
		rm -f $tmpfile
		exit 6
	fi
fi
rm -f $tmpfile

##################################################################################
# Application code goes below. This sample script firstly gets all accessible #
# organizations. Then for each organization, print its name and list all groups' #
# name under it. #
##################################################################################
echo ""
echo "Listing all accessible organizations' group names."
echo ""

curl $curl_opt -so $tmpfile "${api_server_prefix}/rest/o?access_token=${access_token}"
if grep -q Unauthorized $tmpfile ; then
	echo "The saved access token is invalid. Rerun this script to obtain a new one"
	rm -f ${access_token_file}
	exit 7
fi

for org in $(jq -r '.data[] | @base64' $tmpfile); do
	org_name=$(echo $org |base64 --decode | jq -r '.name')
	org_id=$(echo $org |base64 --decode | jq -r '.id')
	echo "Groups under the organization: $org_name"
	curl $curl_opt -s "${api_server_prefix}/rest/o/$org_id/g?access_token=${access_token}" | \
		jq -r '.data[] | .name'
	echo ""
done
rm -f $tmpfile

```

Is there a simple way to convert this code or does it need to be completely re-written?

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [June 25, 2021, 12:28pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/6 "2021-06-25T12:28:44Z")

</div>

It needs to be re-written in my opinion. I would start with getting your tokens and saving them. To start you can save them into tags, then worry about securely storing them later. I have my API helper functions also save and monitor the expiration time of the token. Once expired I automatically refresh the tokens, so I never have to worry about an expired token during a call. Once you have that, it really isn’t that bad to convert a curl into a `system.net.httpPost` call.

If you need some more inspiration, when I have my API project finished, I will be posting it to Ignition Exchange where you can download it and use it as a guide.

You can call this shell script from Ignition using `system.util.execute()` but I don’t think it will do what you need it to this way.

---

<div class="post-metadata">

**Author:** ![taupo](https://avatars.discourse-cdn.com/v4/letter/t/2bfe46/32.png) [@taupo](https://forum.inductiveautomation.com/u/taupo)\
**Post date:** [June 27, 2021, 3:04pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/7 "2021-06-27T15:04:53Z")

</div>

So I can get the following working in postman and PyCharm as a PUT and DELETE but can not get it running in Ignition. Any ideas?

I have tried system.net.httpPut system.net.httpDelete but I keep getting error in the script consul. Any pointers on how to format the information below for it to function in the script editor?

```auto
import http.client

import json

conn = http.client.HTTPSConnection("api.ic.peplink.com")

payload = "{data:{device_ids:[31,32],tag_names:[(CREATE_THE_TAG_HERE)]}}"

headers = {

'Authorization': 'Bearer (REPLACE_WITH_BEARER_ID)',

'Content-Type': 'application/json',

'Cookie': 'JSESSIONID=(REPLACE_WITH_COOKIE)'

}

conn.request("DELETE", "/rest/o/(ORG_ID)/device_tags", payload, headers)

res = conn.getresponse()

data = res.read()

print(data.decode("utf-8"))

```

Thank You

---

<div class="post-metadata">

**Author:** ![Gaurav.Shitole](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gaurav.shitole/32/72050_2.png) [@Gaurav.Shitole](https://forum.inductiveautomation.com/u/Gaurav.Shitole)\
**Post date:** [January 12, 2022, 11:21am UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/8 "2022-01-12T11:21:12Z")

</div>

Did you get this working?

---

<div class="post-metadata">

**Author:** ![Brandon\_VanDenBosch](https://avatars.discourse-cdn.com/v4/letter/b/bc8723/32.png) [@Brandon\_VanDenBosch](https://forum.inductiveautomation.com/u/Brandon_VanDenBosch)\
**Post date:** [July 27, 2022, 2:13am UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/9 "2022-07-27T02:13:05Z")

</div>

Hello, stupid question but how do I find my Peplink Organization\_ID , group\_id , and device\_id ?? Thank you

---

<div class="post-metadata">

**Author:** ![taupo](https://avatars.discourse-cdn.com/v4/letter/t/2bfe46/32.png) [@taupo](https://forum.inductiveautomation.com/u/taupo)\
**Post date:** [July 27, 2022, 1:02pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/10 "2022-07-27T13:02:23Z")

</div>

Hi @Brandon_VanDenBosch  
You can find that info in the URL of each device in InControl2. o = Org ID, n = Group ID & d= Device ID.  
e.g. [https://mars.ic.peplink.com/o/{orgID}/n/{groupID}/d/{deviceID}/overview](https://mars.ic.peplink.com/o/%7BorgID%7D/n/%7BgroupID%7D/d/%7BdeviceID%7D/overview)  
If you need any help with the API’s let me know as I have extensive knowledge of the for both InControl2 & device level APIs.

---

<div class="post-metadata">

**Author:** ![Brandon\_VanDenBosch](https://avatars.discourse-cdn.com/v4/letter/b/bc8723/32.png) [@Brandon\_VanDenBosch](https://forum.inductiveautomation.com/u/Brandon_VanDenBosch)\
**Post date:** [July 27, 2022, 2:23pm UTC](https://forum.inductiveautomation.com/t/ignition-integration-with-peplink-incontrol2-api/48161/11 "2022-07-27T14:23:14Z")

</div>

Taupo, maybe you can help with an API we are looking at to get the “event log” and “event log archive” for all of our devices on InControl2. I’m trying to have the event logs downloaded as CSV, and then input to Caspio our web page application data tables.
