Repository: openwisp/openwisp-controller (language: python)

Issue:
[deps] Update channels
[Channels 3.0 brought some breaking changes](https://channels.readthedocs.io/en/latest/releases/3.0.0.html).

Depends on https://github.com/openwisp/openwisp-notifications/issues/154 and https://github.com/openwisp/django-loci/issues/79.


Discussion / hints:
I am working on this Issue.

Fix patch:
diff --git a/README.rst b/README.rst
index 2c0337700..a0b8907eb 100755
--- a/README.rst
+++ b/README.rst
@@ -2250,7 +2250,31 @@ Ensure you are using one of the available geodjango backends, eg:
 
 For more information about GeoDjango, please refer to the `geodjango documentation <https://docs.djangoproject.com/en/dev/ref/contrib/gis/>`_.
 
-6. Other Settings
+6. Django Channels Setup
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Create ``asgi.py`` in your project folder and add following lines in it:
+
+.. code-block:: python
+
+    from channels.auth import AuthMiddlewareStack
+    from channels.routing import ProtocolTypeRouter, URLRouter
+    from channels.security.websocket import AllowedHostsOriginValidator
+    from django.core.asgi import get_asgi_application
+
+    from openwisp_controller.routing import get_routes
+    # You can also add your routes like this
+    from my_app.routing import my_routes
+
+    application = ProtocolTypeRouter(
+        {   "http": get_asgi_application(),
+            'websocket': AllowedHostsOriginValidator(
+                AuthMiddlewareStack(URLRouter(get_routes() + my_routes))
+            )
+        }
+    )
+
+7. Other Settings
 ~~~~~~~~~~~~~~~~~
 
 Add the following settings to ``settings.py``:
@@ -2259,7 +2283,7 @@ Add the following settings to ``settings.py``:
 
     FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
 
-    ASGI_APPLICATION = 'openwisp_controller.geo.channels.routing.channel_routing'
+    ASGI_APPLICATION = 'my_project.asgi.application'
     CHANNEL_LAYERS = {
         'default': {
             'BACKEND': 'channels.layers.InMemoryChannelLayer'
diff --git a/openwisp_controller/connection/channels/routing.py b/openwisp_controller/connection/channels/routing.py
index 9840e2b65..8cf84dbb9 100644
--- a/openwisp_controller/connection/channels/routing.py
+++ b/openwisp_controller/connection/channels/routing.py
@@ -4,4 +4,8 @@
 
 
 def get_routes(consumer=ow_consumer):
-    return [path('ws/controller/device/<uuid:pk>/command', consumer.CommandConsumer)]
+    return [
+        path(
+            'ws/controller/device/<uuid:pk>/command', consumer.CommandConsumer.as_asgi()
+        )
+    ]
diff --git a/openwisp_controller/geo/channels/routing.py b/openwisp_controller/geo/channels/routing.py
index 000feb557..6c3a31158 100644
--- a/openwisp_controller/geo/channels/routing.py
+++ b/openwisp_controller/geo/channels/routing.py
@@ -11,7 +11,11 @@
 
 
 def get_routes():
-    return [url(location_broadcast_path, LocationBroadcast, name='LocationChannel')]
+    return [
+        url(
+            location_broadcast_path, LocationBroadcast.as_asgi(), name='LocationChannel'
+        )
+    ]
 
 
 # Kept for backward compatibility
diff --git a/requirements.txt b/requirements.txt
index e0be9a77b..37eb01ecb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,14 +3,14 @@ django-sortedm2m>=3.0.0,<3.1.0
 django-reversion>=3.0.5,<3.1.0
 django-x509~=0.9.4
 django-taggit~=1.3.0
-# TODO: change this when next point version of django-loci is released
-django-loci @ https://github.com/openwisp/django-loci/tarball/gsoc-2021/update-openwisp-utils
+# TODO: Need to be changed
+django-loci @ https://github.com/openwisp/django-loci/tarball/master
 django-flat-json-widget~=0.1.3
 # TODO: change this when next point version of openwisp-utils is released
 openwisp-utils[rest] @ https://github.com/openwisp/openwisp-utils/tarball/master
 # TODO: change this when next point version of openwisp-users is released
 openwisp-users @ https://github.com/openwisp/openwisp-users/tarball/master
-# TODO: change this when next point version of openwisp-notifications is released
+# TODO: Need to be changed
 openwisp-notifications @ https://github.com/openwisp/openwisp-notifications/tarball/master
 djangorestframework-gis>=0.12.0,<0.17.0
 netjsonconfig~=0.9.0


Test patch:
diff --git a/openwisp_controller/config/tests/pytest.py b/openwisp_controller/config/tests/pytest.py
index 60ee2ea8f..1a63d053c 100644
--- a/openwisp_controller/config/tests/pytest.py
+++ b/openwisp_controller/config/tests/pytest.py
@@ -25,7 +25,12 @@ class TestDeviceConsumer(CreateDeviceMixin, TestOrganizationMixin):
             'websocket': AllowedHostsOriginValidator(
                 AuthMiddlewareStack(
                     URLRouter(
-                        [path('ws/controller/device/<uuid:pk>/', BaseDeviceConsumer)]
+                        [
+                            path(
+                                'ws/controller/device/<uuid:pk>/',
+                                BaseDeviceConsumer.as_asgi(),
+                            )
+                        ]
                     )
                 )
             )
diff --git a/openwisp_controller/geo/tests/pytest.py b/openwisp_controller/geo/tests/pytest.py
index 576f51867..a050560c7 100644
--- a/openwisp_controller/geo/tests/pytest.py
+++ b/openwisp_controller/geo/tests/pytest.py
@@ -55,7 +55,9 @@ async def _get_request_dict(self, pk=None, user=None):
         return {'pk': pk, 'path': path, 'session': session}
 
     def _get_communicator(self, request_vars, user=None):
-        communicator = WebsocketCommunicator(LocationBroadcast, request_vars['path'])
+        communicator = WebsocketCommunicator(
+            LocationBroadcast.as_asgi(), request_vars['path']
+        )
         if user:
             communicator.scope.update(
                 {
diff --git a/requirements-test.txt b/requirements-test.txt
index 664094d76..2a20b07a0 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -5,7 +5,7 @@ pytest-cov~=2.10.0
 openwisp-utils[qa] @ https://github.com/openwisp/openwisp-utils/tarball/master
 coverage<6.0
 redis>=3.4.1,<4.0.0
-channels_redis~=3.1
+channels_redis~=3.2.0
 django_redis~=4.12
 mock-ssh-server>=0.8.0,<0.9.0
 responses~=0.12.1
diff --git a/tests/openwisp2/routing.py b/tests/openwisp2/asgi.py
similarity index 100%
rename from tests/openwisp2/routing.py
rename to tests/openwisp2/asgi.py
diff --git a/tests/openwisp2/settings.py b/tests/openwisp2/settings.py
index 7cd4b2488..de870750d 100644
--- a/tests/openwisp2/settings.py
+++ b/tests/openwisp2/settings.py
@@ -87,7 +87,7 @@
 
 ROOT_URLCONF = 'openwisp2.urls'
 
-ASGI_APPLICATION = 'openwisp2.routing.application'
+ASGI_APPLICATION = 'openwisp2.asgi.application'
 if not TESTING:
     CHANNEL_LAYERS = {
         'default': {