def create_viewsets(device_type_cls):
    """Generate DRF ViewSets for a DeviceType's models.

    Returns (DeviceViewSet, ReadingViewSet) or (None, None) if DRF is not installed.
    """
    try:
        from rest_framework import viewsets, permissions, decorators, response
    except ImportError:
        return None, None

    from .serializers import create_serializers

    device_model = device_type_cls._device_model
    reading_model = device_type_cls._reading_model
    type_name = device_type_cls.__name__

    DeviceSerializer, ReadingSerializer = create_serializers(device_type_cls)
    if not DeviceSerializer:
        return None, None

    # -- Device ViewSet --

    def get_readings(self, request, pk=None):
        """GET /devices/{id}/readings/?limit=100"""
        device = self.get_object()
        limit = min(int(request.query_params.get("limit", 100)), 1000)
        readings = reading_model.objects.filter(device=device).order_by("-timestamp")[
            :limit
        ]
        serializer = ReadingSerializer(readings, many=True)
        return response.Response(serializer.data)

    readings_action = decorators.action(
        detail=True,
        methods=["get"],
        url_path="readings",
    )(get_readings)

    def provision(self, request, pk=None):
        """POST /devices/{id}/provision/ — generate MQTT credentials."""
        device = self.get_object()
        credentials = device.generate_credentials()
        device.save()

        from ..signals import device_provisioned

        device_provisioned.send(
            sender=device_type_cls,
            device=device,
            credentials=credentials,
        )

        return response.Response(
            {
                "device_id": device.device_id,
                "credentials": credentials,
                "topics": {
                    "data": device_type_cls.get_topic(device.device_id, "data"),
                    "status": device_type_cls.get_topic(device.device_id, "status"),
                    "commands": device_type_cls.get_topic(device.device_id, "cmd"),
                },
            }
        )

    provision_action = decorators.action(
        detail=True,
        methods=["post"],
        url_path="provision",
    )(provision)

    DeviceViewSet = type(
        f"{type_name}DeviceViewSet",
        (viewsets.ModelViewSet,),
        {
            "queryset": device_model.objects.all(),
            "serializer_class": DeviceSerializer,
            "permission_classes": [permissions.IsAuthenticated],
            "readings": readings_action,
            "provision": provision_action,
        },
    )

    # -- Reading ViewSet (read-only) --

    ReadingViewSet = type(
        f"{type_name}ReadingViewSet",
        (viewsets.ReadOnlyModelViewSet,),
        {
            "queryset": reading_model.objects.all(),
            "serializer_class": ReadingSerializer,
            "permission_classes": [permissions.IsAuthenticated],
        },
    )

    return DeviceViewSet, ReadingViewSet
