forked from afanasyev.aa/stratoflights
Compare commits
No commits in common. "master" and "master" have entirely different histories.
7 changed files with 17 additions and 78 deletions
|
|
@ -45,7 +45,6 @@ MEDIA_ROOT = os.getenv('MEDIA_ROOT', os.path.join(BASE_DIR, 'media')) # Куд
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'daphne',
|
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
|
|
@ -104,7 +103,7 @@ ASGI_APPLICATION = 'stratoflights.asgi.application'
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
if not PRODUCTION:
|
if PRODUCTION:
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
|
@ -168,7 +167,7 @@ AUTH_USER_MODEL = 'stratoflights_api.User'
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
||||||
'PAGE_SIZE': 1000,
|
'PAGE_SIZE': 100,
|
||||||
|
|
||||||
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
|
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
|
||||||
|
|
||||||
|
|
@ -197,9 +196,9 @@ CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost:5173,
|
||||||
|
|
||||||
CHANNEL_LAYERS = {
|
CHANNEL_LAYERS = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "channels.layers.InMemoryChannelLayer",
|
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
||||||
# "CONFIG": {
|
"CONFIG": {
|
||||||
# "hosts": [("redis", 6379)],
|
"hosts": [("redis", 6379)],
|
||||||
# },
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ from rest_framework.response import Response
|
||||||
class CustomLimitOffsetPagination(LimitOffsetPagination):
|
class CustomLimitOffsetPagination(LimitOffsetPagination):
|
||||||
limit_query_param = 'limit'
|
limit_query_param = 'limit'
|
||||||
offset_query_param = 'skip'
|
offset_query_param = 'skip'
|
||||||
max_limit = 1000
|
max_limit = 100
|
||||||
default_limit = 10
|
default_limit = 10
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('stratoflights_api', '0001_initial'),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='telemetrypacket',
|
|
||||||
name='user',
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -39,7 +39,7 @@ class Satellite(models.Model):
|
||||||
|
|
||||||
class TelemetryPacket(models.Model):
|
class TelemetryPacket(models.Model):
|
||||||
user = models.ForeignKey(
|
user = models.ForeignKey(
|
||||||
get_user_model(), on_delete=models.SET_NULL, null=True, blank=True)
|
get_user_model(), on_delete=models.CASCADE, default=0)
|
||||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||||
satellite = models.ForeignKey(
|
satellite = models.ForeignKey(
|
||||||
Satellite, on_delete=models.CASCADE, related_name="telemetry")
|
Satellite, on_delete=models.CASCADE, related_name="telemetry")
|
||||||
|
|
@ -50,10 +50,6 @@ class TelemetryPacket(models.Model):
|
||||||
payload = models.JSONField(blank=True, default=dict)
|
payload = models.JSONField(blank=True, default=dict)
|
||||||
raw_data = models.JSONField(blank=True, default=dict)
|
raw_data = models.JSONField(blank=True, default=dict)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
def __str__(self):
|
|
||||||
return f"packet {self.satellite} {self.lat} {self.lon} {self.alt} {self.timestamp}"
|
|
||||||
class Meta:
|
|
||||||
ordering = ["-timestamp"]
|
|
||||||
|
|
||||||
|
|
||||||
class PreditctionTemplate(models.Model):
|
class PreditctionTemplate(models.Model):
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,6 @@ class TelemetryPacketSerializer(serializers.ModelSerializer):
|
||||||
model = TelemetryPacket
|
model = TelemetryPacket
|
||||||
fields = ['id', 'timestamp', 'lat', 'lon', 'alt', 'payload']
|
fields = ['id', 'timestamp', 'lat', 'lon', 'alt', 'payload']
|
||||||
read_only_fields = ['id']
|
read_only_fields = ['id']
|
||||||
extra_kwargs = {'timestamp': {'required': False}}
|
|
||||||
|
|
||||||
|
|
||||||
class SavedPointSerializer(serializers.ModelSerializer):
|
class SavedPointSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from zoneinfo import ZoneInfo
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
class TawhiriClient:
|
class TawhiriClient:
|
||||||
BASE_URL = "http://127.0.0.1:8080/api/v1/prediction"
|
BASE_URL = "https://fly.stratonautica.ru/api/v2/"
|
||||||
TIMEOUT = 15
|
TIMEOUT = 15
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
|
|
@ -156,47 +156,16 @@ class TelemetryListCreateView(generics.ListCreateAPIView):
|
||||||
if not serializer.is_valid():
|
if not serializer.is_valid():
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
try:
|
|
||||||
satellite = Satellite.objects.get(id=pk)
|
|
||||||
except Satellite.DoesNotExist:
|
|
||||||
return Response({"detail": "Satellite not found"}, status=status.HTTP_404_NOT_FOUND)
|
|
||||||
|
|
||||||
validated_data = serializer.validated_data
|
validated_data = serializer.validated_data
|
||||||
|
|
||||||
packet = TelemetryPacket.objects.create(
|
TelemetryPacket.objects.create(timestamp=time.time(),
|
||||||
satellite=satellite,
|
satellite=Satellite.objects.get(id=pk),
|
||||||
user=request.user if request.user.is_authenticated else None,
|
lat=validated_data["lat"],
|
||||||
timestamp=validated_data.get('timestamp', int(time.time())),
|
lon=validated_data["lon"],
|
||||||
lat=validated_data['lat'],
|
alt=validated_data["alt"],
|
||||||
lon=validated_data['lon'],
|
payload=validated_data['payload'],
|
||||||
alt=validated_data['alt'],
|
)
|
||||||
payload=validated_data.get('payload', {}),
|
return Response(serializer.errors, status=status.HTTP_201_CREATED)
|
||||||
)
|
|
||||||
|
|
||||||
# Broadcast to WebSocket subscribers so the tracking page updates live
|
|
||||||
try:
|
|
||||||
from asgiref.sync import async_to_sync
|
|
||||||
from channels.layers import get_channel_layer
|
|
||||||
from .consumers import SatelliteTelemetryConsumer
|
|
||||||
channel_layer = get_channel_layer()
|
|
||||||
if channel_layer is not None:
|
|
||||||
async_to_sync(SatelliteTelemetryConsumer.broadcast_to_satellite_group)(
|
|
||||||
str(pk),
|
|
||||||
{
|
|
||||||
'id': str(packet.id),
|
|
||||||
'timestamp': packet.timestamp,
|
|
||||||
'lat': packet.lat,
|
|
||||||
'lon': packet.lon,
|
|
||||||
'alt': packet.alt,
|
|
||||||
'payload': packet.payload,
|
|
||||||
'raw_data': {},
|
|
||||||
},
|
|
||||||
channel_layer,
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass # WS broadcast is best-effort; don't fail the REST response
|
|
||||||
|
|
||||||
return Response({'id': str(packet.id)}, status=status.HTTP_201_CREATED)
|
|
||||||
|
|
||||||
|
|
||||||
class SessionView(APIView):
|
class SessionView(APIView):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue