# Adding to existing subscriptions via Web API

**URL:** <https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769>\
**Category:** Developer Tools\
**Tags:** subscriptions, web-service\
**Created:** [October 23, 2020, 5:01pm UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769 "2020-10-23T17:01:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![MikeTT](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MikeTT](https://tech-community.robotics.abb.com/u/MikeTT)\
**Post date:** [October 23, 2020, 5:01pm UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769/1 "2020-10-23T17:01:20Z")

</div>

Hello, I am trying to figure out how to have multiple subscriptions via the web API, for example a subscription to the Controller Execution State, and another subscription to a RAPID persistent variable.

I am able to successfully subscribe to either one of these individually using the POST method, my question is how do I then go about adding the second subscription. The documentation states:

“Client can add new subscribable resource to existing subscription-group using PUT method.”

As I understand it, this means I should be using the PUT method, but when I attempt to use it with the same syntax as my previous POST, I get a 405 Method not allowed error. I can also see in the documentation that I am supposed to be supplying a “Group ID” parameter, but I don’t know what this is or how to obtain it.

Any help would be appreciated.

---

<div class="post-metadata">

**Author:** ![dnilsson](https://dub1.discourse-cdn.com/flex005/user_avatar/tech-community.robotics.abb.com/dnilsson/32/795_2.png) [@dnilsson](https://tech-community.robotics.abb.com/u/dnilsson)\
**Post date:** [October 26, 2020, 1:38pm UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769/2 "2020-10-26T13:38:51Z")

</div>

Here’s an example code doing that for python3.

import sys, argparse  
import xml.etree.ElementTree as ET  
from ws4py.client.threadedclient import WebSocketClient  
import requests  
from requests.auth import HTTPDigestAuth

namespace = ‘{[XHTML namespace](http://www.w3.org/1999/xhtml)}’

def print\_event(evt):  
root = ET.fromstring(evt)  
if root.findall(“.//{0}li[@class=‘pnl-ctrlstate-ev’]”.format(namespace)):  
print (“\tController State : " + root.find(”.//{0}li[@class=‘pnl-ctrlstate-ev’]/{0}span".format(namespace)).text)  
if root.findall(“.//{0}li[@class=‘pnl-opmode-ev’]”.format(namespace)):  
print (“\tOperation Mode : " + root.find(”.//{0}li[@class=‘pnl-opmode-ev’]/{0}span".format(namespace)).text)  
if root.findall(“.//{0}li[@class=‘pnl-speedratio-ev’]”.format(namespace)):  
print (“\tSpeed Ratio : " + root.find(”.//{0}li[@class=‘pnl-speedratio-ev’]/{0}span".format(namespace)).text)

# This class encapsulates the Web Socket Callbacks functions.

class RobWebSocketClient(WebSocketClient):  
def opened(self):  
print (“Web Sockect connection established”)

def closed(self, code, reason=None):  
print (“Closed down”, code, reason)

def received\_message(self, event\_xml):  
if event\_xml.is\_text:  
print ("Events : ")  
print\_event(event\_xml.data.decode(“utf-8”))  
else:  
print ("Received Illegal Event " + str(event\_xml))

# The main RobotWare Panel class

class RWPanel:

def **init** (self, host, username, password):  
self.host = host  
self.username = username  
self.password = password  
self.digest\_auth = HTTPDigestAuth(self.username,self.password)  
self.subscription\_url = ‘http://{0}/subscription’.format(self.host)  
self.session = requests.Session()

def subscribe(self):

# Create a payload to subscribe on RobotWare Panel Resources with high priority

payload = {‘resources’:[‘1’,‘2’,‘3’],  
‘1’:‘/rw/panel/speedratio’,  
‘1-p’:‘1’,  
‘2’:‘/rw/panel/ctrlstate’,  
‘2-p’:‘1’,  
‘3’:‘/rw/panel/opmode’,  
‘3-p’:‘1’}

resp = self.session.post(self.subscription\_url , auth=self.digest\_auth, data=payload)  
print ("Initial Events : ")  
print\_event(resp.text)  
if resp.status\_code == 201:  
self.location = resp.headers[‘Location’]  
self.cookie = ‘-http-session-={0}; ABBCX={1}’.format(resp.cookies[‘-http-session-’], resp.cookies[‘ABBCX’])  
return True  
else:  
print ('Error subscribing ’ + str(resp.status\_code))  
return False

def start\_recv\_events(self):  
self.header = [(‘Cookie’,self.cookie)]  
self.ws = RobWebSocketClient(self.location,  
protocols=[‘robapi2\_subscription’],  
headers=self.header)  
self.ws.connect()  
self.ws.run\_forever()

def close(self):  
self.ws.close()

def enable\_http\_debug():  
import logging  
import httplib2 as httplib  
httplib.debuglevel = 1  
logging.basicConfig() # Initialize logging  
logging.getLogger().setLevel(logging.DEBUG)  
requests\_log = logging.getLogger(“requests.packages.urllib3”)  
requests\_log.setLevel(logging.DEBUG)  
requests\_log.propagate = True

def main(argv):  
try:  
parser = argparse.ArgumentParser()  
parser.add\_argument(“-host”,help=“The host to connect. Defaults to localhost on port 80”, default=‘localhost:80’)  
parser.add\_argument(“-user”,help=“The login user name. Defaults to default user name”, default=‘Default User’)  
parser.add\_argument(“-passcode”,help=“The login password. Defaults to default password”, default=‘robotics’)  
parser.add\_argument(“-debug”,help=“Enable HTTP level debugging.”, action=‘store\_true’)  
args = parser.parse\_args()

if args.debug:  
enable\_http\_debug()

rwpanel = RWPanel(args.host, args.user, args.passcode)  
if rwpanel.subscribe():  
rwpanel.start\_recv\_events()  
except KeyboardInterrupt:  
rwpanel.close()

if **name** == “ **main** ”:  
main(sys.argv[1:])

---

<div class="post-metadata">

**Author:** ![MikeTT](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MikeTT](https://tech-community.robotics.abb.com/u/MikeTT)\
**Post date:** [October 26, 2020, 2:42pm UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769/3 "2020-10-26T14:42:53Z")

</div>

Hi dnilsson, thanks for taking the time to reply,

I’m not that familiar with python so please correct me if I’m wrong but it looks like you are initially subscribing to 3 different resources via HTTP POST inside your subscribe function. I can basically do this with my C# code too, the bit I am stuck on is adding another subscription after the first set was already done.

So, in your example, how would you now subscribe to a 4th resource without losing the subscription to the first 3? Do you need to do a whole new POST request which has all 4 resources in the payload?

I was hoping there would be some way of using the PUT method (with just the 4th resource in the payload) to simply get an updated location which would work for all 4 via the websocket. Is this not possible?

EDIT: I guess it’s not such a big deal if I need to subscribe to all 4 resources at once in one big POST request, but then how do I deal with the 3 initial subscriptions, do I need to use the DELETE method to unsubscribe first?

---

<div class="post-metadata">

**Author:** ![dnilsson](https://dub1.discourse-cdn.com/flex005/user_avatar/tech-community.robotics.abb.com/dnilsson/32/795_2.png) [@dnilsson](https://tech-community.robotics.abb.com/u/dnilsson)\
**Post date:** [October 27, 2020, 1:11pm UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769/4 "2020-10-27T13:11:48Z")

</div>

Ok, sorry for my sloppy reading.

Here’s an example of doing that with the use of postman instead so that you don’t have to read python this time.

Here’s the curl:  
curl --digest -u “Default User”:robotics -d “resources=1&1=/rw/panel/ctrlstate&1-p=0” -X POST “[http://localhost/subscription](http://localhost/subscription)”

Here’s thea snippet from the response for POST sub (Unfortunatly the forum itself don’t allow me to send the xml respons and keeps blocking me so I had to cut out the relevant parts):  
``

`
`

`
`

What you want to do now is to extract the subscription group from the response and save that, since it is needed in the PUT request.

Here’s the curl for the PUT request:

curl --digest -u “Default User”:robotics -d “resources=2&1=/rw/panel/opmode;state&1-p=0” -X PUT “[http://localhost/subscription/10](http://localhost/subscription/10)”

Lastly we send the get request for Get subscription group:

curl --digest -u “Default User”:robotics “[http://localhost/subscription/1?action=show](http://localhost/subscription/1?action=show)”

Which gives us the following in the response:  
``

`

`

With that we have confirmed that we successfully subscribed to TWO resources by first initiate a subscription and then add an additional resource by using the PUT request.

Hope this clarifies the procedure for you!

Best regards,  
Daniel

---

<div class="post-metadata">

**Author:** ![MikeTT](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MikeTT](https://tech-community.robotics.abb.com/u/MikeTT)\
**Post date:** [October 27, 2020, 1:35pm UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769/5 "2020-10-27T13:35:44Z")

</div>

Okay, thanks for that, I think I have a better understanding of it now, I will give it a try and let you know how I get on!

---

<div class="post-metadata">

**Author:** ![MikeTT](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MikeTT](https://tech-community.robotics.abb.com/u/MikeTT)\
**Post date:** [October 29, 2020, 10:29am UTC](https://tech-community.robotics.abb.com/t/adding-to-existing-subscriptions-via-web-api/9769/6 "2020-10-29T10:29:19Z")

</div>

Hi Daniel, just confirming that I tried what you suggested and got it working, thanks for the help!
