如何将Socket.io事件发送至Odoo类方法?
问题分析
你当前的Socket.io客户端是独立Python脚本,而self.env是Odoo模型类实例的专属属性,只有在Odoo运行上下文(如模块模型、控制器、内置动作)中才能直接调用。独立脚本未初始化Odoo环境,自然无法使用self.env调用模型方法。
以下是两种可行解决方案:
方案一:将Socket.io客户端集成到Odoo模块中(推荐)
把客户端逻辑嵌入Odoo模块,直接利用Odoo ORM环境调用模型方法,无需跨进程通信。
实现代码(模块models目录下的文件)
import socketio from odoo import models, api from threading import Thread from odoo.service import common from odoo.http import request class LinhafalaAsterisk(models.Model): _name = 'linhafala.asterisk' _description = 'Linhafala Asterisk 集成' def handleEvent(self, data): # 这里写你的业务处理逻辑 print(f"处理WebSocket事件: {data}") # 示例:创建关联记录 # self.create({'event_data': str(data)}) return True def start_websocket_client(self): sio = socketio.Client() @sio.on('connect') def on_connect(): print('已连接WebSocket服务器(端口3001)') @sio.on('disconnect') def on_disconnect(): print('已断开WebSocket连接') @sio.on('message') def on_event(data): print(f'收到服务器事件: {data}') # 直接通过Odoo环境调用模型方法 self.env['linhafala.asterisk'].handleEvent(data) def run_client(): server_url = "http://localhost:3001" sio.connect(server_url) sio.wait() # 启动后台线程运行客户端,避免阻塞Odoo主进程 Thread(target=run_client, daemon=True).start() # 模块安装后自动启动客户端 def post_init_hook(cr, registry): env = api.Environment(cr, common.SUPERUSER_ID, {}) env['linhafala.asterisk'].start_websocket_client()
配置启动逻辑
在模块的__init__.py中添加:
from . import models def post_init_hook(cr, registry): from odoo import api env = api.Environment(cr, 1, {}) env['linhafala.asterisk'].start_websocket_client()
方案二:保持独立脚本,通过Odoo RPC调用模型方法
如果需要客户端独立运行,可通过Odoo的XML-RPC/JSON-RPC远程调用handleEvent方法。
修改后的独立脚本代码
import socketio import xmlrpc.client # Odoo RPC配置,替换为你的实际信息 ODOO_URL = 'http://localhost:8069' ODOO_DB = '你的数据库名' ODOO_USER = '你的用户名' ODOO_PASSWORD = '你的密码' # 初始化RPC客户端 common = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/common') uid = common.authenticate(ODOO_DB, ODOO_USER, ODOO_PASSWORD, {}) models = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/object') sio = socketio.Client() @sio.on('connect') def on_connect(): print('已连接WebSocket服务器(端口3001)') @sio.on('disconnect') def on_disconnect(): print('已断开WebSocket连接') @sio.on('message') def on_event(data): print(f'收到服务器事件: {data}') # 通过RPC调用Odoo模型方法 try: models.execute_kw( ODOO_DB, uid, ODOO_PASSWORD, 'linhafala.asterisk', 'handleEvent', [data] # 传递给handleEvent的参数 ) print("事件已成功发送至Odoo") except Exception as e: print(f"发送事件失败: {str(e)}") if __name__ == "__main__": server_url = "http://localhost:3001" sio.connect(server_url) sio.wait()
注意事项
- 确保
linhafala.asterisk的handleEvent方法是公共方法(方法名无前缀_),否则无法通过RPC调用 - 若使用JSON-RPC,请求格式需调整,逻辑与XML-RPC一致
内容的提问来源于stack exchange,提问作者Darken Machava
相关产品推荐
相关产品推荐

