由于在ABB机器人论坛找不到关于web seriver订阅的相关代码,大部分是C#和python的代码,而且采用之前按的AJAX的轮询方法显示机器人报警信息在真实的机器人上运行会导致示教器卡停,采用订阅方式则不会,我这边也是参考论坛大佬的python代码进行编写的,页面没有编写完成,不过订阅的结构就是ajax+webScoket,下面贴出主要代码:
进行机器人程序数据订阅
function SubscribeRobotData(){
console.log("开始订阅");
var payload = "resources=1&1=/rw/panel/opmode&1-p=1&"+
"resources=3&3=/rw/panel/ctrlstate&3-p=1&"+
"resources=4&4=/rw/panel/speedratio&4-p=1&"+
"resources=5&5=/rw/rapid/execution;ctrlexecstate&5-p=1&"+
"resources=6&6=/rw/elog/0&6-p=1";
var headerUrl = "";
var Rheaders = "";
var SubResource = new XMLHttpRequest();
SubResource.onreadystatechange = function () {
if (SubResource.readyState == this.HEADERS_RECEIVED) {
Rheaders = SubResource.getAllResponseHeaders;
headerUrl = SubResource.getResponseHeader("Location");
}
if (SubResource.readyState == 4 ) {
testWebSocket(headerUrl, Rheaders);
console.log(SubResource.responseText);
ShowData(SubResource.responseText);
GetRobotIdentity();
}
}
var url = "/subscription"
SubResource.open("POST", url, true, "Default User", "robotics");
SubResource.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
SubResource.send(payload);
}
订阅完成后也对应完成了通讯握手,后面进行webScoket进行程序监控就可以了
function testWebSocket(wsurl, rheaders) {
console.log(wsurl);
websocket = new WebSocket(url = wsurl, protocols = ['robapi2_subscription'], Headers = rheaders);
websocket.onopen = function (evt) {
//onOpen(evt)
console.log("Connected to: " + event.data);
};
websocket.onclose = function (evt) {
//onClose(evt)
};
websocket.onmessage = function (evt) {
//onMessage()
console.log(evt.data)
if (evt.data.search("pnl-opmode-ev")>0){
console.log("更新了运动模式")
document.getElementById("RobotRunMethon").innerHTML =strTran( evt.data.match(/(?<=class\=\"opmode\"\>)(.*?)(?=\<\/span\>)/g));
}
if (evt.data.search("pnl-ctrlstate-ev")>0){
console.log("更新了电机状态")
document.getElementById("RobotMotorState").innerHTML = strTran(evt.data.match(/(?<=class\=\"ctrlstate\"\>)(.*?)(?=\<\/span\>)/g));
}
if (evt.data.search("rap-ctrlexecstate-ev")>0){
console.log("更新了运行状态")
document.getElementById("RobotState").innerHTML =strTran( evt.data.match(/(?<=class\=\"ctrlexecstate\"\>)(.*?)(?=\<\/span\>)/g));
}
if (evt.data.search("pnl-speedratio-ev")>0){
console.log("更新了运行速度")
document.getElementById("RobotSpeed").innerHTML = evt.data.match(/(?<=class\=\"speedratio\"\>)(.*?)(?=\<\/span\>)/g);
}
if (evt.data.search("elog-message-ev")>0){
console.log("更新了显示信息")
var LogDomain = evt.data.match(/(?<=class\=\"seqnum\"\>)(.*?)(?=\<\/span\>)/g);
console.log(LogDomain)
get_Robot_Elog(LogDomain);
}
};
websocket.onerror = function (evt) {
//onError(evt)
};
}
监控后会返回对应的HTML文档,每个数据的HTML都有特殊的字符串,进行字符串搜索得出对应的数据更新,然后通过正则截取需要的部分进行显示
function ShowData(responseText){
if (responseText.search("pnl-opmode-ev")>0){
document.getElementById("RobotRunMethon").innerHTML =strTran( responseText.match(/(?<=class\=\"opmode\"\>)(.*?)(?=\<\/span\>)/g));
}
if (responseText.search("pnl-ctrlstate-ev")>0){
document.getElementById("RobotMotorState").innerHTML = strTran(responseText.match(/(?<=class\=\"ctrlstate\"\>)(.*?)(?=\<\/span\>)/g));
}
if (responseText.search("rap-ctrlexecstate-ev")>0){
document.getElementById("RobotState").innerHTML = strTran(responseText.match(/(?<=class\=\"ctrlexecstate\"\>)(.*?)(?=\<\/span\>)/g));
}
if (responseText.search("pnl-speedratio-ev")>0){
document.getElementById("RobotSpeed").innerHTML = responseText.match(/(?<=class\=\"speedratio\"\>)(.*?)(?=\<\/span\>)/g);
}
}
由于程序主要是以订阅机器人显示信息为主,下面是显示信息的程序
function get_Robot_Elog(LogDomain) {
var temCode = new Array();
var temDesc = new Array();
var temDate = new Array();
var rwServiceResource = new XMLHttpRequest();
rwServiceResource.onreadystatechange = function () {
if (rwServiceResource.readyState == 4 && rwServiceResource.status == 200) {
var obj = JSON.parse(rwServiceResource.responseText);
var service = obj._embedded._state[0];
for (let index = 0; index < 5; index++) {
temCode[index] = document.getElementById("rapid_Elog_code" + String(index)).innerHTML
temDesc[index] = document.getElementById("rapid_Elog_desc" + String(index)).innerHTML
temDate[index] = document.getElementById("rapid_Elog_date" + String(index)).innerHTML
}
for (let index = 0; index < 4; index++) {
document.getElementById("rapid_Elog_code" + String(index+1)).innerHTML = temCode[index];
document.getElementById("rapid_Elog_desc" + String(index+1)).innerHTML = temDesc[index];
document.getElementById("rapid_Elog_date" + String(index+1)).innerHTML = temDate[index];
}
document.getElementById("rapid_Elog_code" + String(0)).innerHTML = service.code;
document.getElementById("rapid_Elog_desc" + String(0)).innerHTML = service.title;
document.getElementById("rapid_Elog_date" + String(0)).innerHTML = service.tstamp;
}
}
var Elog_path = "/rw/elog/0/"+LogDomain+"?lang=zh&json=1"
rwServiceResource.open("GET", Elog_path, true, "Default User", "robotics");
rwServiceResource.send();
}
主要的订阅程序就这么多,下面是参考的python程序
import xml.etree.ElementTree as ET
from ws4py.client.threadedclient import WebSocketClient
import requests
import json
import sys, argparse
from requests.auth import HTTPDigestAuth
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)
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))
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):
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(str(resp.status_code))
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 main():
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')
mes = rwpanel('localhost:80', 'Default User', 'robotics')
if rwpanel.subscribe(mes):
rwpanel.start_recv_events(mes)
except KeyboardInterrupt:
rwpanel.close()
if __name__ == "__main__":
main()
# main(sys.argv[1:])
python程序下载对应库文件后可以直接运行
由于我这边页面还没有完成,后面完成后再进行分享;