odoo from 表单自定义按钮 执行JS代码 并调用websoket

业务场景:
集成串口读取RFID数据。由于串口是需要在客户端本地电脑执行才可以拿到数据
但是系统 部署在服务器 不能直接调用串口。
解决方案:
利用websoket通信 调用串口 传输 读取到的串口数据,解决服务器与本地之间的通信

本场景是基于odoo开源系统进行开发

1、首先在from表单增加按钮

odoo from 表单自定义按钮 执行JS代码 并调用websoket_第1张图片
2、JS监听按钮事件 并集成websoket

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()

至此所有功能结束。

你可能感兴趣的:(odoo,websocket,odoo)