业务场景:
集成串口读取RFID数据。由于串口是需要在客户端本地电脑执行才可以拿到数据
但是系统 部署在服务器 不能直接调用串口。
解决方案:
利用websoket通信 调用串口 传输 读取到的串口数据,解决服务器与本地之间的通信
本场景是基于odoo开源系统进行开发
1、首先在from表单增加按钮
odoo.define('demo.websoket', function (require) {
"use strict";
var FormView = require('web.FormView');
var FormRenderer = require('web.FormRenderer');
var view_registry = require('web.view_registry');
var session = require('web.session');
var host = "ws://127.0.0.1:8082/";
var socket=null;
var SpsServiceFormRenderer = FormRenderer.extend({
events: _.extend({}, FormRenderer.prototype.events, {
'click .read_rfid_data': 'read_rfid_data',
'click .close_rfid_server': 'close_rfid_server',
}),
init: function () {
this._super.apply(this, arguments);
},
start : function(){
var self =this;
if (socket == null){
socket = new WebSocket(host);
socket.onopen = function (msg) {
console.log("Begin Connection!");
};
socket.onmessage = function (msg) {
console.log(msg.data);
if (msg.data.indexOf("RFID") != -1){
var data=msg.data.split(":")[1];
// 芯片入库
self._rpc({
model: 'xxxxx',
method: 'do_action_rfid',
args: {'rfid':data},
}).then(res => {
// 发送成功消息
self.call("notification", "notify", {
type: 'info',
title: 'RFID通知',
message: 'RFID处理完成,请核对数据',
sticky: false,
});
})
}
};
}
this._super.apply(this, arguments);
},
read_rfid_data: function () {
var self=this;
self.do_send_rfid("start_rfid","RFID读取中,请操作RFID设备");
},
do_send_rfid: function (cmd,message) {
if (socket.readyState==1){
this.call("notification", "notify", {
type: 'info',
title: 'RFID通知',
message: message,
sticky: false,
});
console.log(message);
socket.send(cmd);
}else{
console.log("RFID is not ready!");
this.call("notification", "notify", {
type: 'warning',
title: '通知',
message: 'RFID设备未连接,请刷新页面',
sticky: false,
});
}
},
close_rfid_server: function () {
var self=this;
self.do_send_rfid("stop_rfid","RFID收集数据中,请稍后...");
},
})
var SpsServiceFormView = FormView.extend({
jsLibs: [],
config: _.extend({}, FormView.prototype.config, {
Renderer: SpsServiceFormRenderer,
}),
});
view_registry.add('read_rfid', SpsServiceFormView);
return {
Renderer: SpsServiceFormRenderer,
};
})
3、客户端本地电脑程序
# coding=utf8
import struct, socket
import hashlib
import threading
from base64 import b64encode
from uhf.reader import *
connectionlist = {}
g_client = GClient()
RFID_DATA = ['E2000016590C0251220B0F0F']
def decode(data):
if not len(data):
return False
# 用数据包的第二个字节,与127作与位运算,拿到前七位。
length = data[1] & 127
# 这七位在数据头部分成为payload,如果payload等于126,就要再扩展2个字节。
# 如果等于127,就要再扩展8个字节。
# 如果小于等于125,那它就占这一个字节。
if length == 126:
extend_payload_len = data[2:4]
mask = data[4:8]
decoded = data[8:]
elif length == 127:
extend_payload_len = data[2:10]
mask = data[10:14]
decoded = data[14:]
else:
extend_payload_len = None
mask = data[2:6]
decoded = data[6:]
byte_list = bytearray()
# 当payload确定之后,再往后数4个字节,这4个字节成为masking key,再之后的内容就是接收到的数据部分。
# 数据部分的每一字节都要和masking key作异或位运算,得出来的结果就是真实的数据内容。
for i in range(len(decoded)):
chunk = decoded[i] ^ mask[i % 4]
byte_list.append(chunk)
new_str = str(byte_list, encoding="utf-8")
return new_str
def encode(data):
data = str.encode(data)
head = b'\x81'
if len(data) < 126:
head += struct.pack('B', len(data))
elif len(data) <= 0xFFFF:
head += struct.pack('!BH', 126, len(data))
else:
head += struct.pack('!BQ', 127, len(data))
return head + data
def sendMessage(message):
global connectionlist
for connection in connectionlist.values():
try:
connection.send(encode(message))
except Exception as e:
print(e)
connection.close()
# del connectionlist['connection' + str(connection.fileno())]
continue
def deleteconnection(item):
global connectionlist
del connectionlist['connection' + item]
class WebSocket(threading.Thread):
GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
def __init__(self, conn, index, name, remote, path="/"):
threading.Thread.__init__(self)
self.conn = conn
self.index = index
self.name = name
self.remote = remote
self.path = path
self.buffer = ""
def run(self):
print('Socket%s Start!' % self.index)
headers = {}
self.handshaken = False
def receivedEpc(epcInfo: LogBaseEpcInfo):
if epcInfo.result == 0:
RFID_DATA.append(epcInfo.epc.upper())
print('串口数据:', epcInfo.epc)
def receivedEpcOver(epcOver: LogBaseEpcOver):
print("LogBaseEpcOver")
while True:
if self.handshaken == False:
print('Socket%s Start Handshaken with %s!' % (self.index, self.remote))
self.buffer += bytes.decode(self.conn.recv(1024))
if self.buffer.find('\r\n\r\n') != -1:
header, data = self.buffer.split('\r\n\r\n', 1)
for line in header.split("\r\n")[1:]:
key, value = line.split(": ", 1)
headers[key] = value
headers["Location"] = ("ws://%s%s" % (headers["Host"], self.path))
key = headers['Sec-WebSocket-Key']
token = b64encode(hashlib.sha1(str.encode(str(key + self.GUID))).digest())
handshake = "HTTP/1.1 101 Switching Protocols\r\n" \
"Upgrade: websocket\r\n" \
"Connection: Upgrade\r\n" \
"Sec-WebSocket-Accept: " + bytes.decode(token) + "\r\n" \
"WebSocket-Origin: " + str(
headers["Origin"]) + "\r\n" \
"WebSocket-Location: " + str(headers["Location"]) + "\r\n\r\n"
self.conn.send(str.encode(str(handshake)))
self.handshaken = True
print('Socket%s Handshaken with %s success!' % (self.index, self.remote))
sendMessage('Welcome, ' + self.name + ' !')
else:
msg = decode(self.conn.recv(1024))
if msg == 'stop_rfid':
print('结束读取串口数据')
# 停止读epc
stop = MsgBaseStop()
if g_client.sendSynMsg(stop) == 0:
print(stop.rtMsg)
g_client.close()
print('串口数据:{}'.format(RFID_DATA))
sendMessage("RFID:{}".format(str(RFID_DATA)))
elif msg == 'close':
print('关闭连接')
RFID_DATA.clear()
deleteconnection(str(self.index))
self.conn.close()
elif msg == 'start_rfid':
print('开始读取串口数据')
# 利用串口发送数据
if g_client.openSerial(("COM7", 115200)):
# if g_client.openTcp(("192.168.1.168", 8160)):
# 订阅标签回调
g_client.callEpcInfo = receivedEpc
g_client.callEpcOver = receivedEpcOver
# 读epc
msg = MsgBaseInventoryEpc(antennaEnable=EnumG.AntennaNo_1.value,
inventoryMode=EnumG.InventoryMode_Inventory.value)
if g_client.sendSynMsg(msg) == 0:
print(msg.rtMsg)
self.buffer = ""
class WebSocketServer(object):
def __init__(self):
self.socket = None
def begin(self):
print('WebSocketServer Start!')
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(("127.0.0.1", 8082))
self.socket.listen(50)
global connectionlist
i = 0
while True:
connection, address = self.socket.accept()
username = address[0]
newSocket = WebSocket(connection, i, username, address)
newSocket.start()
connectionlist['connection' + str(i)] = connection
i = i + 1
if __name__ == "__main__":
server = WebSocketServer()
server.begin()
至此所有功能结束。