Adding to existing subscriptions via Web API

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.

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}’

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:])

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?

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

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

Lastly we send the get request for Get subscription group:

curl --digest -u “Default User”:robotics “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

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!

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