Adding to existing subscriptions via Web API
MikeTT
✭
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.
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.
Tagged:
0
Best Answer
-
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):
<code><a href="subscription/10" rel="group"></a></code>
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:
<code><form method="delete" action="10" id="unsubscribe-group"></form><form method="delete" action="10/rw/panel/ctrlstate" id="unsubscribe-resource"></form><form method="delete" action="10/rw/panel/opmode" id="unsubscribe-resource"></form></code>
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,
Daniel5
Answers
-
Here's an example code doing that for python3.import sys, argparseimport xml.etree.ElementTree as ETfrom ws4py.client.threadedclient import WebSocketClientimport requestsfrom requests.auth import HTTPDigestAuthnamespace = '{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 classclass RWPanel:def __init__(self, host, username, password):self.host = hostself.username = usernameself.password = passwordself.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 prioritypayload = {'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 Trueelse:print ('Error subscribing ' + str(resp.status_code))return Falsedef 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 loggingimport httplib2 as httplibhttplib.debuglevel = 1logging.basicConfig() # Initialize logginglogging.getLogger().setLevel(logging.DEBUG)requests_log = logging.getLogger("requests.packages.urllib3")requests_log.setLevel(logging.DEBUG)requests_log.propagate = Truedef 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:])0
-
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?0 -
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!0
-
Hi Daniel, just confirming that I tried what you suggested and got it working, thanks for the help!1
Categories
- All Categories
- 5.5K RobotStudio
- 395 UpFeed
- 18 Tutorials
- 13 RobotApps
- 297 PowerPacs
- 405 RobotStudio S4
- 1.8K Developer Tools
- 249 ScreenMaker
- 2.7K Robot Controller
- 310 IRC5
- 59 OmniCore
- 7 RCS (Realistic Controller Simulation)
- 785 RAPID Programming
- AppStudio
- 3 RobotStudio AR Viewer
- 18 Wizard Easy Programming
- 105 Collaborative Robots
- 4 Job listings