pyopensky 2.5__tar.gz → 2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyopensky-2.5 → pyopensky-2.7}/PKG-INFO +4 -2
- {pyopensky-2.5 → pyopensky-2.7}/pyproject.toml +2 -1
- {pyopensky-2.5 → pyopensky-2.7}/readme.md +1 -1
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/config.py +1 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/schema.py +94 -50
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/trino.py +87 -20
- {pyopensky-2.5 → pyopensky-2.7}/license.txt +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/__init__.py +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/api.py +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/impala.py +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/py.typed +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/rest.py +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/s3.py +0 -0
- {pyopensky-2.5 → pyopensky-2.7}/src/pyopensky/time.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyopensky
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7
|
|
4
4
|
Summary: A Python interface for OpenSky database
|
|
5
|
+
Home-page: https://github.com/open-aviation/pyopensky/
|
|
5
6
|
License: MIT
|
|
6
7
|
Author: Xavier Olive
|
|
7
8
|
Author-email: git@xoolive.org
|
|
@@ -21,13 +22,14 @@ Requires-Dist: pyjwt (>=2.7.0)
|
|
|
21
22
|
Requires-Dist: tqdm (>=4.65.0)
|
|
22
23
|
Requires-Dist: trino[sqlalchemy] (>=0.322)
|
|
23
24
|
Requires-Dist: typing-extensions (>=4.5.0)
|
|
25
|
+
Project-URL: Repository, https://github.com/open-aviation/pyopensky/
|
|
24
26
|
Description-Content-Type: text/markdown
|
|
25
27
|
|
|
26
28
|
# pyopensky
|
|
27
29
|
|
|
28
30
|
The `pyopensky` Python library provides functions to download data from the OpenSky Network live API and historical databases. It aims at making ADS-B and Mode S data from OpenSky easily accessible in the Python programming environment.
|
|
29
31
|
|
|
30
|
-
Full documentation on https://open-aviation.github.io/pyopensky
|
|
32
|
+
Full documentation on <https://open-aviation.github.io/pyopensky>
|
|
31
33
|
|
|
32
34
|
## Installation
|
|
33
35
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "pyopensky"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.7"
|
|
4
4
|
description = "A Python interface for OpenSky database"
|
|
5
|
+
repository = "https://github.com/open-aviation/pyopensky/"
|
|
5
6
|
authors = ["Xavier Olive <git@xoolive.org>", "Junzi Sun <j.sun-1@tudelft.nl>"]
|
|
6
7
|
license = "MIT"
|
|
7
8
|
readme = "readme.md"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The `pyopensky` Python library provides functions to download data from the OpenSky Network live API and historical databases. It aims at making ADS-B and Mode S data from OpenSky easily accessible in the Python programming environment.
|
|
4
4
|
|
|
5
|
-
Full documentation on https://open-aviation.github.io/pyopensky
|
|
5
|
+
Full documentation on <https://open-aviation.github.io/pyopensky>
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -98,6 +98,7 @@ class Resolution(TypedDict, total=False):
|
|
|
98
98
|
NAME_RESOLUTION: dict[str, Resolution] = {
|
|
99
99
|
# Cache configuration
|
|
100
100
|
"cache_dir": dict(
|
|
101
|
+
environment_variable="OPENSKY_CACHE",
|
|
101
102
|
opensky_category="cache",
|
|
102
103
|
opensky_name="path",
|
|
103
104
|
traffic_category="cache",
|
|
@@ -67,6 +67,17 @@ class UTCTimestampFloat(TypeDecorator[pd.Timestamp]):
|
|
|
67
67
|
return super().process_bind_param(value, dialect)
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
class AddressString(TypeDecorator[str]):
|
|
71
|
+
"""Automatic coercing of icao24 addresses into low characters."""
|
|
72
|
+
|
|
73
|
+
impl = String
|
|
74
|
+
|
|
75
|
+
def process_bind_param(self, value: str | None, dialect: Dialect) -> Any:
|
|
76
|
+
if isinstance(value, str):
|
|
77
|
+
return value.lower()
|
|
78
|
+
return super().process_bind_param(value, dialect)
|
|
79
|
+
|
|
80
|
+
|
|
70
81
|
class CallsignString(TypeDecorator[str]):
|
|
71
82
|
"""Automatic coercing of callsigns into 8-char left padded strings.
|
|
72
83
|
|
|
@@ -122,7 +133,7 @@ class TrackRow:
|
|
|
122
133
|
|
|
123
134
|
@dataclass
|
|
124
135
|
class AirportCandidateRow:
|
|
125
|
-
icao24:
|
|
136
|
+
icao24: Address
|
|
126
137
|
horizdistance: int
|
|
127
138
|
vertdistance: int
|
|
128
139
|
|
|
@@ -180,6 +191,7 @@ Track = List[TrackRow]
|
|
|
180
191
|
Sensors = List[SensorRow]
|
|
181
192
|
|
|
182
193
|
Callsign = Annotated[str, mapped_column(CallsignString)]
|
|
194
|
+
Address = Annotated[str, mapped_column(AddressString)]
|
|
183
195
|
|
|
184
196
|
|
|
185
197
|
class Base(DeclarativeBase):
|
|
@@ -188,6 +200,7 @@ class Base(DeclarativeBase):
|
|
|
188
200
|
AirportCandidates: AirportCandidateType,
|
|
189
201
|
Track: TrackType,
|
|
190
202
|
Callsign: CallsignString,
|
|
203
|
+
Address: AddressString,
|
|
191
204
|
Sensors: SensorsType,
|
|
192
205
|
}
|
|
193
206
|
|
|
@@ -196,7 +209,7 @@ class StateVectorsData4(Base):
|
|
|
196
209
|
__tablename__ = "state_vectors_data4"
|
|
197
210
|
|
|
198
211
|
time: Mapped[pd.Timestamp]
|
|
199
|
-
icao24: Mapped[
|
|
212
|
+
icao24: Mapped[Address]
|
|
200
213
|
lat: Mapped[float]
|
|
201
214
|
lon: Mapped[float]
|
|
202
215
|
velocity: Mapped[float]
|
|
@@ -218,7 +231,7 @@ class StateVectorsData4(Base):
|
|
|
218
231
|
class FlightsData4(Base):
|
|
219
232
|
__tablename__ = "flights_data4"
|
|
220
233
|
|
|
221
|
-
icao24: Mapped[
|
|
234
|
+
icao24: Mapped[Address]
|
|
222
235
|
firstseen: Mapped[pd.Timestamp]
|
|
223
236
|
estdepartureairport: Mapped[str]
|
|
224
237
|
lastseen: Mapped[pd.Timestamp]
|
|
@@ -243,7 +256,7 @@ class FlightsData4(Base):
|
|
|
243
256
|
class FlightsData5(Base):
|
|
244
257
|
__tablename__ = "flights_data5"
|
|
245
258
|
|
|
246
|
-
icao24: Mapped[
|
|
259
|
+
icao24: Mapped[Address]
|
|
247
260
|
firstseen: Mapped[pd.Timestamp]
|
|
248
261
|
estdepartureairport: Mapped[str]
|
|
249
262
|
lastseen: Mapped[pd.Timestamp]
|
|
@@ -280,17 +293,7 @@ class RawTable(Protocol):
|
|
|
280
293
|
mintime: Mapped[pd.Timestamp]
|
|
281
294
|
maxtime: Mapped[pd.Timestamp]
|
|
282
295
|
msgcount: Mapped[int]
|
|
283
|
-
icao24: Mapped[
|
|
284
|
-
message: Mapped[str]
|
|
285
|
-
isid: Mapped[bool]
|
|
286
|
-
flightstatus: Mapped[int]
|
|
287
|
-
downlinkrequest: Mapped[int]
|
|
288
|
-
utilitymsg: Mapped[int]
|
|
289
|
-
interrogatorid: Mapped[int]
|
|
290
|
-
identifierdesignator: Mapped[int]
|
|
291
|
-
valuecode: Mapped[int]
|
|
292
|
-
altitude: Mapped[float]
|
|
293
|
-
identity: Mapped[str]
|
|
296
|
+
icao24: Mapped[Address]
|
|
294
297
|
|
|
295
298
|
# Whatever, we pick this one as primary key BUT
|
|
296
299
|
# - this is not true
|
|
@@ -306,7 +309,7 @@ class AcasData4(Base):
|
|
|
306
309
|
mintime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
307
310
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
308
311
|
msgcount: Mapped[int]
|
|
309
|
-
icao24: Mapped[
|
|
312
|
+
icao24: Mapped[Address]
|
|
310
313
|
message: Mapped[str]
|
|
311
314
|
isid: Mapped[bool]
|
|
312
315
|
flightstatus: Mapped[int]
|
|
@@ -332,7 +335,7 @@ class AllcallRepliesData4(Base):
|
|
|
332
335
|
mintime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
333
336
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
334
337
|
msgcount: Mapped[int]
|
|
335
|
-
icao24: Mapped[
|
|
338
|
+
icao24: Mapped[Address]
|
|
336
339
|
message: Mapped[str]
|
|
337
340
|
isid: Mapped[bool]
|
|
338
341
|
flightstatus: Mapped[int]
|
|
@@ -358,16 +361,9 @@ class IdentificationData4(Base):
|
|
|
358
361
|
mintime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
359
362
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
360
363
|
msgcount: Mapped[int]
|
|
361
|
-
icao24: Mapped[
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
flightstatus: Mapped[int]
|
|
365
|
-
downlinkrequest: Mapped[int]
|
|
366
|
-
utilitymsg: Mapped[int]
|
|
367
|
-
interrogatorid: Mapped[int]
|
|
368
|
-
identifierdesignator: Mapped[int]
|
|
369
|
-
valuecode: Mapped[int]
|
|
370
|
-
altitude: Mapped[float]
|
|
364
|
+
icao24: Mapped[Address]
|
|
365
|
+
emittercategory: Mapped[int]
|
|
366
|
+
ftc: Mapped[int]
|
|
371
367
|
identity: Mapped[str]
|
|
372
368
|
|
|
373
369
|
# Whatever, we pick this one as primary key BUT
|
|
@@ -385,16 +381,33 @@ class OperationalStatusData4(Base):
|
|
|
385
381
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
386
382
|
msgcount: Mapped[int]
|
|
387
383
|
icao24: Mapped[str]
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
384
|
+
subtypecode: Mapped[int]
|
|
385
|
+
unknowncapcode: Mapped[bool]
|
|
386
|
+
unknownopcode: Mapped[bool]
|
|
387
|
+
hasoperationaltcas: Mapped[int]
|
|
388
|
+
has1090esin: Mapped[bool]
|
|
389
|
+
supportsairreferencedvelocity: Mapped[int]
|
|
390
|
+
haslowtxpower: Mapped[int]
|
|
391
|
+
supportstargetstatereport: Mapped[int]
|
|
392
|
+
supportstargetchangereport: Mapped[int]
|
|
393
|
+
hasuatin: Mapped[bool]
|
|
394
|
+
nacv: Mapped[int]
|
|
395
|
+
nicsupplementc: Mapped[int]
|
|
396
|
+
hastcasresolutionadvisory: Mapped[bool]
|
|
397
|
+
hasactiveidentswitch: Mapped[bool]
|
|
398
|
+
usessingleantenna: Mapped[bool]
|
|
399
|
+
systemdesignassurance: Mapped[int]
|
|
400
|
+
gpsantennaoffset: Mapped[int]
|
|
401
|
+
airplanelength: Mapped[int]
|
|
402
|
+
airplanewidth: Mapped[float]
|
|
403
|
+
version: Mapped[int]
|
|
404
|
+
nicsupplementa: Mapped[bool]
|
|
405
|
+
positionnac: Mapped[float]
|
|
406
|
+
geometricverticalaccuracy: Mapped[int]
|
|
407
|
+
sourceintegritylevel: Mapped[int]
|
|
408
|
+
barometricaltitudeintegritycode: Mapped[int]
|
|
409
|
+
trackheadinginfo: Mapped[int]
|
|
410
|
+
horizontalreferencedirection: Mapped[bool]
|
|
398
411
|
|
|
399
412
|
# Whatever, we pick this one as primary key BUT
|
|
400
413
|
# - this is not true
|
|
@@ -410,7 +423,7 @@ class PositionData4(Base):
|
|
|
410
423
|
mintime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
411
424
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
412
425
|
msgcount: Mapped[int]
|
|
413
|
-
icao24: Mapped[
|
|
426
|
+
icao24: Mapped[Address]
|
|
414
427
|
nicsuppla: Mapped[bool]
|
|
415
428
|
hcr: Mapped[float]
|
|
416
429
|
nic: Mapped[int]
|
|
@@ -442,7 +455,7 @@ class RollcallRepliesData4(Base):
|
|
|
442
455
|
mintime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
443
456
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
444
457
|
msgcount: Mapped[int]
|
|
445
|
-
icao24: Mapped[
|
|
458
|
+
icao24: Mapped[Address]
|
|
446
459
|
message: Mapped[str]
|
|
447
460
|
isid: Mapped[bool]
|
|
448
461
|
flightstatus: Mapped[int]
|
|
@@ -468,17 +481,48 @@ class VelocityData4(Base):
|
|
|
468
481
|
mintime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
469
482
|
maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
470
483
|
msgcount: Mapped[int]
|
|
471
|
-
icao24: Mapped[
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
484
|
+
icao24: Mapped[Address]
|
|
485
|
+
supersonic: Mapped[bool]
|
|
486
|
+
intentchange: Mapped[bool]
|
|
487
|
+
ifrcapability: Mapped[bool]
|
|
488
|
+
nac: Mapped[int]
|
|
489
|
+
ewvelocity: Mapped[float]
|
|
490
|
+
nsvelocity: Mapped[float]
|
|
491
|
+
baro: Mapped[bool]
|
|
492
|
+
vertrate: Mapped[float]
|
|
493
|
+
geominurbaro: Mapped[float] # typo confirmed
|
|
494
|
+
heading: Mapped[float]
|
|
495
|
+
velocity: Mapped[float]
|
|
496
|
+
|
|
497
|
+
# Whatever, we pick this one as primary key BUT
|
|
498
|
+
# - this is not true
|
|
499
|
+
# - we still need one column with a primary key
|
|
500
|
+
hour: Mapped[pd.Timestamp] = mapped_column(primary_key=True)
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
class FlarmRaw(Base):
|
|
504
|
+
__tablename__ = "flarm_raw"
|
|
505
|
+
|
|
506
|
+
sensortype: Mapped[str]
|
|
507
|
+
sensorlatitude: Mapped[float]
|
|
508
|
+
sensorlongitude: Mapped[float]
|
|
509
|
+
sensoraltitude: Mapped[int]
|
|
510
|
+
timeatserver: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
511
|
+
timeatsensor: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
512
|
+
timestamp: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
|
|
513
|
+
rawmessage: Mapped[str]
|
|
514
|
+
crc: Mapped[str]
|
|
515
|
+
rawsoftmessage: Mapped[str]
|
|
516
|
+
sensorname: Mapped[str]
|
|
517
|
+
ntperror: Mapped[float]
|
|
518
|
+
userfreqcorrection: Mapped[float]
|
|
519
|
+
autofreqcorrection: Mapped[float]
|
|
520
|
+
frequency: Mapped[float]
|
|
521
|
+
channel: Mapped[int]
|
|
522
|
+
snrdetector: Mapped[float]
|
|
523
|
+
snrdemodulator: Mapped[float]
|
|
524
|
+
typeogn: Mapped[bool]
|
|
525
|
+
crccorrect: Mapped[bool]
|
|
482
526
|
|
|
483
527
|
# Whatever, we pick this one as primary key BUT
|
|
484
528
|
# - this is not true
|
|
@@ -33,6 +33,7 @@ import pandas as pd
|
|
|
33
33
|
from .api import HasBounds, OpenSkyDBAPI
|
|
34
34
|
from .config import cache_path, trino_password, trino_username
|
|
35
35
|
from .schema import (
|
|
36
|
+
FlarmRaw,
|
|
36
37
|
FlightsData4,
|
|
37
38
|
FlightsData5,
|
|
38
39
|
RawTable,
|
|
@@ -296,7 +297,7 @@ class Trino(OpenSkyDBAPI):
|
|
|
296
297
|
else start_ts + pd.Timedelta("1d")
|
|
297
298
|
)
|
|
298
299
|
|
|
299
|
-
stmt = select(Table).with_only_columns(
|
|
300
|
+
stmt = select(Table).with_only_columns(
|
|
300
301
|
Table.icao24,
|
|
301
302
|
Table.firstseen,
|
|
302
303
|
Table.estdepartureairport,
|
|
@@ -307,21 +308,17 @@ class Trino(OpenSkyDBAPI):
|
|
|
307
308
|
*(extra_columns if extra_columns is not None else []),
|
|
308
309
|
)
|
|
309
310
|
|
|
310
|
-
stmt = self.stmt_where_str(stmt, icao24, Table.icao24)
|
|
311
|
-
stmt = self.stmt_where_str(
|
|
312
|
-
stmt,
|
|
313
|
-
callsign,
|
|
314
|
-
Table.callsign, # type: ignore
|
|
315
|
-
)
|
|
311
|
+
stmt = self.stmt_where_str(stmt, icao24, Table.icao24)
|
|
312
|
+
stmt = self.stmt_where_str(stmt, callsign, Table.callsign)
|
|
316
313
|
stmt = self.stmt_where_str(
|
|
317
314
|
stmt,
|
|
318
315
|
departure_airport,
|
|
319
|
-
Table.estdepartureairport,
|
|
316
|
+
Table.estdepartureairport,
|
|
320
317
|
)
|
|
321
318
|
stmt = self.stmt_where_str(
|
|
322
319
|
stmt,
|
|
323
320
|
arrival_airport,
|
|
324
|
-
Table.estarrivalairport,
|
|
321
|
+
Table.estarrivalairport,
|
|
325
322
|
)
|
|
326
323
|
if airport is not None and arrival_airport is not None:
|
|
327
324
|
raise RuntimeError("airport may not be set if arrival_airport is")
|
|
@@ -330,8 +327,8 @@ class Trino(OpenSkyDBAPI):
|
|
|
330
327
|
stmt = self.stmt_where_str(
|
|
331
328
|
stmt,
|
|
332
329
|
airport,
|
|
333
|
-
Table.estdepartureairport,
|
|
334
|
-
Table.estarrivalairport,
|
|
330
|
+
Table.estdepartureairport,
|
|
331
|
+
Table.estarrivalairport,
|
|
335
332
|
)
|
|
336
333
|
|
|
337
334
|
if departure_airport is not None:
|
|
@@ -383,6 +380,7 @@ class Trino(OpenSkyDBAPI):
|
|
|
383
380
|
departure_airport: None | str = None,
|
|
384
381
|
arrival_airport: None | str = None,
|
|
385
382
|
airport: None | str = None,
|
|
383
|
+
time_buffer: None | str | pd.Timedelta = None,
|
|
386
384
|
cached: bool = True,
|
|
387
385
|
compress: bool = False,
|
|
388
386
|
limit: None | int = None,
|
|
@@ -435,6 +433,10 @@ class Trino(OpenSkyDBAPI):
|
|
|
435
433
|
:param airport: a string for the ICAO identifier of the airport. Selects
|
|
436
434
|
flights departing from or arriving at the airport between the two
|
|
437
435
|
timestamps;
|
|
436
|
+
:param time_buffer: (default: None) time buffer used to extend time
|
|
437
|
+
bounds for flights in the OpenSky flight tables: requests will get
|
|
438
|
+
flights between ``start - time_buffer`` and ``stop + time_buffer``.
|
|
439
|
+
If no airport is specified, the parameter is ignored.
|
|
438
440
|
|
|
439
441
|
.. warning::
|
|
440
442
|
|
|
@@ -519,18 +521,26 @@ class Trino(OpenSkyDBAPI):
|
|
|
519
521
|
|
|
520
522
|
flight_query = flight_table.subquery()
|
|
521
523
|
fd4 = aliased(FlightsData4, alias=flight_query, adapt_on_names=True)
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
.
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
)
|
|
529
|
-
.
|
|
524
|
+
|
|
525
|
+
if isinstance(time_buffer, str):
|
|
526
|
+
time_buffer = pd.Timedelta(time_buffer)
|
|
527
|
+
|
|
528
|
+
stmt = select(StateVectorsData4).join(
|
|
529
|
+
flight_query,
|
|
530
|
+
(fd4.icao24 == StateVectorsData4.icao24)
|
|
531
|
+
& (fd4.callsign == StateVectorsData4.callsign),
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
if time_buffer is None:
|
|
535
|
+
stmt = stmt.where(
|
|
530
536
|
StateVectorsData4.time >= fd4.firstseen,
|
|
531
537
|
StateVectorsData4.time <= fd4.lastseen,
|
|
532
538
|
)
|
|
533
|
-
|
|
539
|
+
else:
|
|
540
|
+
stmt = stmt.where(
|
|
541
|
+
StateVectorsData4.time >= (fd4.firstseen - time_buffer),
|
|
542
|
+
StateVectorsData4.time <= (fd4.lastseen + time_buffer),
|
|
543
|
+
)
|
|
534
544
|
|
|
535
545
|
stmt = self.stmt_where_str(stmt, icao24, StateVectorsData4.icao24)
|
|
536
546
|
stmt = self.stmt_where_str(stmt, callsign, StateVectorsData4.callsign)
|
|
@@ -610,6 +620,63 @@ class Trino(OpenSkyDBAPI):
|
|
|
610
620
|
|
|
611
621
|
return res
|
|
612
622
|
|
|
623
|
+
def flarm(
|
|
624
|
+
self,
|
|
625
|
+
start: timelike,
|
|
626
|
+
stop: None | timelike = None,
|
|
627
|
+
*args: ColumnExpressionArgument[bool],
|
|
628
|
+
sensor_name: None | str | list[str] = None,
|
|
629
|
+
cached: bool = True,
|
|
630
|
+
compress: bool = False,
|
|
631
|
+
limit: None | int = None,
|
|
632
|
+
correct_only: bool = True,
|
|
633
|
+
extra_columns: tuple[InstrumentedAttribute[Any], ...] = (),
|
|
634
|
+
**kwargs: Any,
|
|
635
|
+
) -> None | pd.DataFrame:
|
|
636
|
+
start_ts = to_datetime(start)
|
|
637
|
+
stop_ts = (
|
|
638
|
+
to_datetime(stop)
|
|
639
|
+
if stop is not None
|
|
640
|
+
else start_ts + pd.Timedelta("1d")
|
|
641
|
+
)
|
|
642
|
+
stmt = select(FlarmRaw).with_only_columns(
|
|
643
|
+
FlarmRaw.sensoraltitude,
|
|
644
|
+
FlarmRaw.sensorlatitude,
|
|
645
|
+
FlarmRaw.sensorlongitude,
|
|
646
|
+
FlarmRaw.sensorname,
|
|
647
|
+
FlarmRaw.timestamp,
|
|
648
|
+
FlarmRaw.timeatserver,
|
|
649
|
+
FlarmRaw.timeatsensor,
|
|
650
|
+
FlarmRaw.rawmessage,
|
|
651
|
+
*extra_columns,
|
|
652
|
+
)
|
|
653
|
+
if correct_only:
|
|
654
|
+
stmt = stmt.where(FlarmRaw.crccorrect)
|
|
655
|
+
stmt = stmt.where(FlarmRaw.rawmessage.is_not(None))
|
|
656
|
+
|
|
657
|
+
if sensor_name is not None:
|
|
658
|
+
stmt = self.stmt_where_str(stmt, sensor_name, FlarmRaw.sensorname)
|
|
659
|
+
|
|
660
|
+
for condition in args:
|
|
661
|
+
stmt = stmt.where(condition)
|
|
662
|
+
|
|
663
|
+
stmt = stmt.where(
|
|
664
|
+
FlarmRaw.timestamp >= start_ts,
|
|
665
|
+
FlarmRaw.timestamp <= stop_ts,
|
|
666
|
+
FlarmRaw.hour >= start_ts.floor("1h"),
|
|
667
|
+
FlarmRaw.hour < stop_ts.ceil("1h"),
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
if limit is not None:
|
|
671
|
+
stmt = stmt.limit(limit)
|
|
672
|
+
|
|
673
|
+
res = self.query(stmt, cached=cached, compress=compress)
|
|
674
|
+
|
|
675
|
+
if res.shape[0] == 0:
|
|
676
|
+
return None
|
|
677
|
+
|
|
678
|
+
return res
|
|
679
|
+
|
|
613
680
|
def rawdata(
|
|
614
681
|
self,
|
|
615
682
|
start: timelike,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|