我有一个业余爱好,那就是建造自动船。我现在使用Vuejs前端和Django后端构建了一个GUI。在此GUI中,我可以在地图上看到船,并向其发送命令。这些命令通过ZeroMQ sockets发送,效果很好。
我正在使用Django channels将命令从前端通过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套接字上的船位置,并通过Websocket将其发送到前端。
我当然可以简单地将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, '')
但是我显然不能在while True
中包含Consumer
循环。所以从这里我不确定该怎么办。我实际上不知道这是否可能,因为Django Channels似乎是专门为websockets设计的。我想我可以开始使用多线程或多处理库,但这对我来说是未知的领域。
有人知道在Django频道中是否以及如何制作ZeroMQ侦听器吗?
答案 0 :(得分:2)
可以通过https://channels.readthedocs.io/en/latest/topics/channel_layers.html#using-outside-of-consumers
从单独的脚本直接向消费者发送消息。当新客户在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"])