问题
I am trying to get familiar with Django channels
and web-sockets
.
I have a task - constantly streaming data to whoever connects to the channel.
Currently, this is a piece of code from official tutorial with some improvements.
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = f'chat_{self.room_name}'
if not hasattr(self, 'vehicle'):
# this produses constant data stream
self.vehicle = connect('/dev/ttyACM0', wait_ready=True, rate=4)
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
# this part does not work!
await self.send(text_data=json.dumps({
'message': {
'mess': "Hi",
'yaw': self.vehicle._yaw,
'pitch': self.vehicle._pitch,
'roll': self.vehicle._roll,
}
}))
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
But now this code disconnects without showing anything in the front. I have found this answer, but that loop also does not work.
If I move that while loop to the separate method and call it from receive
method (which I won't show here for now to be short) - it works, but when a new user enters the channel, he doesn't see messages from the while loop. But after restarting the loop, messages are sent to all users.
How can I make the data stream available for all users at any time they enter the channel?
回答1:
This worked:
class ChatConsumer(AsyncWebsocketConsumer):
vehicle_keeper = []
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = f'chat_{self.room_name}'
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
if not self.vehicle_keeper:
self.vehicle = connect('/dev/ttyACM0', wait_ready=True, rate=4)
self.vehicle_keeper.append(self.vehicle)
else:
self.vehicle = self.vehicle_keeper[0]
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'drone_position',
'message': "HELLO!"
}
)
async def drone_position(self, event):
while True:
await asyncio.sleep(1)
await self.send(text_data=json.dumps({
'message': {
'mess': event['message'],
'yaw': self.vehicle._yaw,
'pitch': self.vehicle._pitch,
'roll': self.vehicle._roll,
}
}))
The key is in vehicle_keeper
list, which keeps vehicle connection in a global list and when new consumer comes - it uses existing connection and not making its own.
来源:https://stackoverflow.com/questions/54480779/constant-data-stream-with-django-channels