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

news2024/11/27 16:24:49

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

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

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

在这里插入图片描述
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()

至此所有功能结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/615591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度解析:2023年软件测试的10个新趋势和挑战

随着技术的飞速发展&#xff0c;软件测试的角色和责任也在经历重大转变。我们在2023年目前所面临的一些新趋势和挑战值得所有从业人员关注。以下是这些主要趋势和挑战的深度分析。 趋势一&#xff1a;人工智能和机器学习在测试中的应用 AI和ML正在越来越多地应用于软件测试&am…

给httprunnermanager接口自动化测试平台演示参数化(五)

文章目录 一、背景1.1、前情回顾 二、参数化实现三、总结 一、背景 参数化&#xff0c;在使用httprunner框架的时候&#xff0c;参数话说实在的不是很实用&#xff0c;因为更多是场景化的用例编写&#xff0c;不用过多的去参数化批量执行&#xff0c;无非也就是登录注册查询啥的…

数据库系统概论 ---知识点大全(期末复习版)

&#xff08;一&#xff09;绪论 数据(Data)&#xff1a;是数据库中存储的基本对象 数据的定义&#xff1a;描述事物的符号记录 数据的种类&#xff1a;文字、图形、图象、声音等 数据的特点&#xff1a;数据与其语义是不可分的 数据库(Database,简称DB)&#xff1a;是长期…

数据结构与算法-跳表详解

我们知道如果一个数组是有序的&#xff0c;查询的时候可以使用二分法进行查询&#xff0c;时间复杂度可以降到 O(logn) &#xff0c;但如果链表是有序的&#xff0c;我们仍然是从前往后一个个查找&#xff0c;这样显然很慢&#xff0c;这个时候我们可以使用跳表&#xff08;Ski…

chatgpt赋能python:Python如何依次取字符——一种简单有效的方法

Python如何依次取字符——一种简单有效的方法 1. 介绍 Python 常常被用于编写文本处理脚本&#xff0c;而文本处理中的一个常见任务就是依次取字符。本文将介绍一种简单高效的方法&#xff0c;让您可以在 Python 中便捷地完成此操作。 2. 如何依次取字符 Python 中的字符串…

黑客入门必备指南

在探讨黑客如何入门之前&#xff0c;首先我们的思想要端正。 作为一名黑客&#xff0c;必须要有正直善良的价值观。 或许你听过这么一句话“能力越大&#xff0c;责任越大”作为一名黑客就是如此&#xff0c;黑客的技术越精湛&#xff0c;能力就越大&#xff0c;就越不能去干…

spark入门 Linux模式 Local模式 (二)

一、下载对应的spark包 https://archive.apache.org/dist/spark/spark-3.0.0/ 我这里下载的是spark-3.0.0-bin-hadoop3.2.tgz 二、解压 tar -zvxf spark-3.0.0-bin-hadoop3.2.tgz三、启动 再解压路径的bin目录执行下 ./spark-shell 四、测试 WordCount代码例子 sc.textFil…

接口测试-使用mock生产随机数据

在做接口测试的时候&#xff0c;有的接口需要进行大量的数据进行测试&#xff0c;还不能是重复的数据&#xff0c;这个时候就需要随机生产数据进行测试了。这里教导大家使用mock.js生成各种随机数据。 一、什么是mock.js mock.js是用于生成随*机数据&#xff0c;拦截 Ajax 请…

uniapp引入uView正确步骤及误区

1.导入uview组件库 2.导入成功后在main.js里引入 import uView from /uni_modules/uview-ui Vue.use(uView)3.在App.vue里引入样式文件 import "/uni_modules/uview-ui/index.scss";4.在pages.json里添加配置 "easycom": {"^u-(.*)": "/…

大聪明教你学Java | parallelStream().forEach() 的踩坑日记

前言 &#x1f34a;作者简介&#xff1a; 不肯过江东丶&#xff0c;一个来自二线城市的程序员&#xff0c;致力于用“猥琐”办法解决繁琐问题&#xff0c;让复杂的问题变得通俗易懂。 &#x1f34a;支持作者&#xff1a; 点赞&#x1f44d;、关注&#x1f496;、留言&#x1f4…

springboot学生管理系统(含源码+数据库)

本次系统开发所用到的Java语言、Spring框架、SpringMVC框架、MyBatis框架、SpringBoot框架以及MySQL。 1.系统分析 &#xff08;1&#xff09;教师管理需求&#xff0c;学校想轻松的查阅指定教师的信息&#xff0c;学校对教师进行一个基本的信息管理&#xff0c;学校可以方便…

【python】脚本编写

这里写自定义目录标题 欢迎使用python来编写脚本环境搭建 欢迎使用python来编写脚本 测试方向&#xff0c;测试报告&#xff0c;单元测试 环境搭建 python环境搭建 下载地址 https://www.python.org/ 文档 https://docs.python.org/3/ pycharm的环境 使用chatgpt来实现代码功…

【安全架构】

概念 安全是产品的属性&#xff0c;安全的目标是保障产品里信息资产的保密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integrity&#xff09;和可用性&#xff08;Availability&#xff09;&#xff0c;简记为CIA。 保密性&#xff1a; 保障信息资产不被未…

通过Visual Studio诊断工具定位软件CPU瓶颈

通过VS诊断工具定位软件CPU瓶颈 前情提示&#xff1a;正常情况下我们使用调试模式会看不到诊断工具窗口&#xff0c;控制台会报“无法启动标准收集器。请尝试修复 Visual Studio 的安装。 (HRESULT: 0xe1110002)”这样的错误。 解决方式&#xff1a;通过[Downloads - Visual St…

00后是太恐怖了,工作没两年,跳槽到我们公司起薪20K都快接近我了

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&…

【JAVA】---逆波兰表达式

一. 逆波兰表达式的介绍 逆波兰表达式又称为后缀表达式&#xff0c;代表的含义是操作数在前&#xff0c;运算符在后。 比如&#xff1a;12&#xff0c;用逆波兰表达式来写的话&#xff0c;就是12。 而12这种写法称为中缀表达式&#xff0c;即运算符在两个操作数之间&#xff0c…

Office Visio 2019安装教程

哈喽&#xff0c;大家好。今天一起学习的是Visio 2019的安装&#xff0c;这是一个绘制流程图的软件&#xff0c;用有效的绘图表达信息&#xff0c;比任何文字都更加形象和直观。Office Visio 是office软件系列中负责绘制流程图和示意图的软件&#xff0c;便于IT和商务人员就复杂…

测试老鸟总结,自动化测试难点挑战应对方法,我的进阶之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

Redis 高级数据结构 HyperLogLog

介绍 HyperLogLog(Hyper[ˈhaɪpə(r)])并不是一种新的数据结构(实际类型为字符串类型)&#xff0c;而是一种基数算法,通过HyperLogLog可以 利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是IP、Email、ID等。如果你负责开发维护一个大型的网站&#xff0c;有一天…