有可能在Django Channels Consumer中使用ZeroMQ套接字吗



我有一个建造自主船的业余项目。我现在使用Vuejs前端和Django后端构建了一个GUI。在这个GUI中,我可以在地图上看到船,并向它发送命令。这些命令通过ZeroMQ套接字发送,效果很好。

我使用Django通道将命令从前端通过websocket发送到后端,然后从那里通过ZeroMQ套接字发送。我的消费者(效果很好(如下所示:

import zmq
from channels.generic.websocket import WebsocketConsumer
from .tools import get_vehicle_ip_address, get_vehicle_steer_socket
context = zmq.Context()
class SteerConsumer(WebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.forward_steer_socket = get_vehicle_steer_socket(context, get_vehicle_ip_address())
def connect(self):
self.accept()
def receive(self, text_data):
print("Passing on the commands from the frontend:", text_data, "to the boat")
self.forward_steer_socket.send_string(text_data)

除此之外,我还通过ZeroMQ套接字从船上接收位置信息,并将其保存到数据库中。我在一个单独的脚本中运行它,前端只需每2秒轮询后端一次更新。这是接收船只信息的脚本:

import os
import django
import zmq
os.environ['DJANGO_SETTINGS_MODULE'] = 'server.settings'
django.setup()
# Socket to receive the boat location
context = zmq.Context()
location_socket = context.socket(zmq.SUB)
location_socket.setsockopt(zmq.CONFLATE, True)
location_socket.bind('tcp://*:6001')
location_socket.setsockopt_string(zmq.SUBSCRIBE, '')
while True:
boat_location = location_socket.recv_json()
print(boat_location)
# HERE I STORE THE BOAT LOCATION in the DB

我现在想把这个location_socket添加到Consumer,这样Consumer也可以在ZeroMQ套接字上接收船的位置,并通过Web套接字将其发送到前端。

当然,我可以简单地将location_socket添加到Consumer__init__()方法中,如下所示:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.forward_steer_socket = get_vehicle_steer_socket(context, get_vehicle_ip_address())
self.location_socket = context.socket(zmq.SUB)
self.location_socket.setsockopt(zmq.CONFLATE, True)
self.location_socket.bind('tcp://*:6001')
self.location_socket.setsockopt_string(zmq.SUBSCRIBE, '')

但是我显然不能在Consumer中包括while True循环。所以从现在开始,我不知道该怎么办。事实上,我甚至不知道这是否可能,因为Django频道似乎是专门为websocket制作的。我想我可以开始使用多线程或多处理库,但这对我来说是未知的领域

有人知道在Django通道中是否以及如何制作ZeroMQ侦听器吗?

可以通过以下方式从分离的脚本直接向消费者发送消息:https://channels.readthedocs.io/en/latest/topics/channel_layers.html#using-消费者外部

当新客户端在SteerConsumer内连接到您的消费者时,您就有了该客户端唯一的self.channel_name。要向消费者发送消息,您只需要执行(在您的示例中,来自分离的脚本(:

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
# "channel_name" should be replaced for the proper name of course
channel_layer.send("channel_name", {
"type": "chat.message",
"text": "Hello there!",
})

并在您的SteerConsumer方法中添加以处理此消息:

def chat_message(self, event):
# Handles the "chat.message" event when it's sent to us.
self.send(text_data=event["text"])

最新更新