pyopensky 2.4__tar.gz → 2.6__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.
@@ -1,7 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyopensky
3
- Version: 2.4
3
+ Version: 2.6
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](https://open-aviation.github.io/pyopensky)
31
33
 
32
34
  ## Installation
33
35
 
@@ -55,13 +57,16 @@ See details in the [documentation](https://open-aviation.github.io/pyopensky/cre
55
57
 
56
58
  ## Usage
57
59
 
60
+ > [!IMPORTANT]
61
+ > The Impala shell is now deprecated. Please upgrade to Trino.
62
+
58
63
  - from the [REST API](https://open-aviation.github.io/pyopensky/rest.html):
59
64
 
60
65
  ```python
61
66
  from pyopensky.rest import REST
62
-
67
+
63
68
  rest = REST()
64
-
69
+
65
70
  rest.states()
66
71
  rest.tracks(icao24)
67
72
  rest.routes(callsign)
@@ -69,25 +74,16 @@ See details in the [documentation](https://open-aviation.github.io/pyopensky/cre
69
74
  rest.arrival(airport, begin, end)
70
75
  rest.departure(airport, begin, end)
71
76
  ```
72
- - from the [Impala](https://open-aviation.github.io/pyopensky/impala.html) shell (requires authentication):
73
77
 
74
- ```python
75
- from pyopensky.impala import Impala
76
-
77
- impala = Impala()
78
- # full description of the whole set of parameters in the documentation
79
- impala.flightlist(start, stop, *, airport, callsign, icao24)
80
- impala.history(start, stop, *, callsign, icao24, bounds)
81
- impala.rawdata(start, stop, *, callsign, icao24, bounds)
82
- ```
83
78
  - from the [Trino](https://open-aviation.github.io/pyopensky/trino.html) database (requires authentication):
84
79
 
85
80
  ```python
86
81
  from pyopensky.trino import Trino
87
-
82
+
88
83
  trino = Trino()
89
84
  # full description of the whole set of parameters in the documentation
90
85
  trino.flightlist(start, stop, *, airport, callsign, icao24)
91
86
  trino.history(start, stop, *, callsign, icao24, bounds)
92
87
  trino.rawdata(start, stop, *, callsign, icao24, bounds)
93
88
  ```
89
+
@@ -1,7 +1,8 @@
1
1
  [tool.poetry]
2
2
  name = "pyopensky"
3
- version = "2.4"
3
+ version = "2.6"
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](https://open-aviation.github.io/pyopensky)
6
6
 
7
7
  ## Installation
8
8
 
@@ -30,13 +30,16 @@ See details in the [documentation](https://open-aviation.github.io/pyopensky/cre
30
30
 
31
31
  ## Usage
32
32
 
33
+ > [!IMPORTANT]
34
+ > The Impala shell is now deprecated. Please upgrade to Trino.
35
+
33
36
  - from the [REST API](https://open-aviation.github.io/pyopensky/rest.html):
34
37
 
35
38
  ```python
36
39
  from pyopensky.rest import REST
37
-
40
+
38
41
  rest = REST()
39
-
42
+
40
43
  rest.states()
41
44
  rest.tracks(icao24)
42
45
  rest.routes(callsign)
@@ -44,25 +47,15 @@ See details in the [documentation](https://open-aviation.github.io/pyopensky/cre
44
47
  rest.arrival(airport, begin, end)
45
48
  rest.departure(airport, begin, end)
46
49
  ```
47
- - from the [Impala](https://open-aviation.github.io/pyopensky/impala.html) shell (requires authentication):
48
50
 
49
- ```python
50
- from pyopensky.impala import Impala
51
-
52
- impala = Impala()
53
- # full description of the whole set of parameters in the documentation
54
- impala.flightlist(start, stop, *, airport, callsign, icao24)
55
- impala.history(start, stop, *, callsign, icao24, bounds)
56
- impala.rawdata(start, stop, *, callsign, icao24, bounds)
57
- ```
58
51
  - from the [Trino](https://open-aviation.github.io/pyopensky/trino.html) database (requires authentication):
59
52
 
60
53
  ```python
61
54
  from pyopensky.trino import Trino
62
-
55
+
63
56
  trino = Trino()
64
57
  # full description of the whole set of parameters in the documentation
65
58
  trino.flightlist(start, stop, *, airport, callsign, icao24)
66
59
  trino.history(start, stop, *, callsign, icao24, bounds)
67
60
  trino.rawdata(start, stop, *, callsign, icao24, bounds)
68
- ```
61
+ ```
@@ -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: str
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[str]
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[str]
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[str]
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[str]
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[str]
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[str]
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[str]
362
- message: Mapped[str]
363
- isid: Mapped[bool]
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
- message: Mapped[str]
389
- isid: Mapped[bool]
390
- flightstatus: Mapped[int]
391
- downlinkrequest: Mapped[int]
392
- utilitymsg: Mapped[int]
393
- interrogatorid: Mapped[int]
394
- identifierdesignator: Mapped[int]
395
- valuecode: Mapped[int]
396
- altitude: Mapped[float]
397
- identity: Mapped[str]
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[str]
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[str]
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[str]
472
- message: Mapped[str]
473
- isid: Mapped[bool]
474
- flightstatus: Mapped[int]
475
- downlinkrequest: Mapped[int]
476
- utilitymsg: Mapped[int]
477
- interrogatorid: Mapped[int]
478
- identifierdesignator: Mapped[int]
479
- valuecode: Mapped[int]
480
- altitude: Mapped[float]
481
- identity: Mapped[str]
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,
@@ -119,6 +120,8 @@ class Trino(OpenSkyDBAPI):
119
120
  if token is not None
120
121
  else OAuth2Authentication(),
121
122
  http_scheme="https",
123
+ # https://github.com/trinodb/trino-python-client/discussions/456
124
+ legacy_prepared_statements=True,
122
125
  ),
123
126
  )
124
127
  return engine
@@ -381,9 +384,11 @@ class Trino(OpenSkyDBAPI):
381
384
  departure_airport: None | str = None,
382
385
  arrival_airport: None | str = None,
383
386
  airport: None | str = None,
387
+ time_buffer: None | str | pd.Timedelta = None,
384
388
  cached: bool = True,
385
389
  compress: bool = False,
386
390
  limit: None | int = None,
391
+ selected_columns: tuple[InstrumentedAttribute[Any] | str, ...] = (),
387
392
  **kwargs: Any,
388
393
  ) -> None | pd.DataFrame:
389
394
  """Get Traffic from the OpenSky Trino database.
@@ -413,6 +418,10 @@ class Trino(OpenSkyDBAPI):
413
418
  :param bounds: sets a geographical footprint. Either an **airspace or
414
419
  shapely shape** (requires the bounds attribute); or a **tuple of
415
420
  float** (west, south, east, north);
421
+ :param selected_columns: specify the columns you want to retrieve. When
422
+ empty, use all columns of the StateVectorsData4 table. You may
423
+ escape column names as str. **Always** escape names from the
424
+ FlightsData4 table.
416
425
 
417
426
  **Airports**
418
427
 
@@ -428,6 +437,10 @@ class Trino(OpenSkyDBAPI):
428
437
  :param airport: a string for the ICAO identifier of the airport. Selects
429
438
  flights departing from or arriving at the airport between the two
430
439
  timestamps;
440
+ :param time_buffer: (default: None) time buffer used to extend time
441
+ bounds for flights in the OpenSky flight tables: requests will get
442
+ flights between ``start - time_buffer`` and ``stop + time_buffer``.
443
+ If no airport is specified, the parameter is ignored.
431
444
 
432
445
  .. warning::
433
446
 
@@ -475,7 +488,7 @@ class Trino(OpenSkyDBAPI):
475
488
  )
476
489
  .where(
477
490
  FlightsData4.day >= start_ts.floor("1d"),
478
- FlightsData4.day <= start_ts.ceil("1d"),
491
+ FlightsData4.day <= stop_ts.ceil("1d"),
479
492
  )
480
493
  )
481
494
 
@@ -512,18 +525,26 @@ class Trino(OpenSkyDBAPI):
512
525
 
513
526
  flight_query = flight_table.subquery()
514
527
  fd4 = aliased(FlightsData4, alias=flight_query, adapt_on_names=True)
515
- stmt = (
516
- select(StateVectorsData4)
517
- .join(
518
- flight_query,
519
- (fd4.icao24 == StateVectorsData4.icao24)
520
- & (fd4.callsign == StateVectorsData4.callsign),
521
- )
522
- .where(
528
+
529
+ if isinstance(time_buffer, str):
530
+ time_buffer = pd.Timedelta(time_buffer)
531
+
532
+ stmt = select(StateVectorsData4).join(
533
+ flight_query,
534
+ (fd4.icao24 == StateVectorsData4.icao24)
535
+ & (fd4.callsign == StateVectorsData4.callsign),
536
+ )
537
+
538
+ if time_buffer is None:
539
+ stmt = stmt.where(
523
540
  StateVectorsData4.time >= fd4.firstseen,
524
541
  StateVectorsData4.time <= fd4.lastseen,
525
542
  )
526
- )
543
+ else:
544
+ stmt = stmt.where(
545
+ StateVectorsData4.time >= (fd4.firstseen - time_buffer),
546
+ StateVectorsData4.time <= (fd4.lastseen + time_buffer),
547
+ )
527
548
 
528
549
  stmt = self.stmt_where_str(stmt, icao24, StateVectorsData4.icao24)
529
550
  stmt = self.stmt_where_str(stmt, callsign, StateVectorsData4.callsign)
@@ -568,8 +589,86 @@ class Trino(OpenSkyDBAPI):
568
589
  stmt = stmt.where(
569
590
  StateVectorsData4.time >= start_ts,
570
591
  StateVectorsData4.time <= stop_ts,
571
- StateVectorsData4.hour >= start_ts.floor("1H"),
572
- StateVectorsData4.hour < stop_ts.ceil("1H"),
592
+ StateVectorsData4.hour >= start_ts.floor("1h"),
593
+ StateVectorsData4.hour < stop_ts.ceil("1h"),
594
+ )
595
+
596
+ def transform_column(col: str) -> InstrumentedAttribute[Any]:
597
+ if "." in col:
598
+ table, column = col.split(".")
599
+ MATCH = {
600
+ "StateVectorsData4": StateVectorsData4,
601
+ "FlightsData4": fd4,
602
+ }
603
+ return getattr(MATCH[table], column) # type: ignore
604
+ if candidate := getattr(StateVectorsData4, col, None):
605
+ return candidate # type: ignore
606
+ if candidate := getattr(fd4, col, None):
607
+ return candidate # type: ignore
608
+ raise ValueError(f"Unknown column: {col}")
609
+
610
+ if len(selected_columns) > 0:
611
+ columns = (
612
+ transform_column(col) if isinstance(col, str) else col
613
+ for col in selected_columns
614
+ )
615
+ stmt = stmt.with_only_columns(*columns)
616
+
617
+ if limit is not None:
618
+ stmt = stmt.limit(limit)
619
+
620
+ res = self.query(stmt, cached=cached, compress=compress)
621
+
622
+ if res.shape[0] == 0:
623
+ return None
624
+
625
+ return res
626
+
627
+ def flarm(
628
+ self,
629
+ start: timelike,
630
+ stop: None | timelike = None,
631
+ *args: ColumnExpressionArgument[bool],
632
+ sensor_name: None | str | list[str] = None,
633
+ cached: bool = True,
634
+ compress: bool = False,
635
+ limit: None | int = None,
636
+ correct_only: bool = True,
637
+ extra_columns: tuple[InstrumentedAttribute[Any], ...] = (),
638
+ **kwargs: Any,
639
+ ) -> None | pd.DataFrame:
640
+ start_ts = to_datetime(start)
641
+ stop_ts = (
642
+ to_datetime(stop)
643
+ if stop is not None
644
+ else start_ts + pd.Timedelta("1d")
645
+ )
646
+ stmt = select(FlarmRaw).with_only_columns(
647
+ FlarmRaw.sensoraltitude,
648
+ FlarmRaw.sensorlatitude,
649
+ FlarmRaw.sensorlongitude,
650
+ FlarmRaw.sensorname,
651
+ FlarmRaw.timestamp,
652
+ FlarmRaw.timeatserver,
653
+ FlarmRaw.timeatsensor,
654
+ FlarmRaw.rawmessage,
655
+ *extra_columns,
656
+ )
657
+ if correct_only:
658
+ stmt = stmt.where(FlarmRaw.crccorrect)
659
+ stmt = stmt.where(FlarmRaw.rawmessage.is_not(None))
660
+
661
+ if sensor_name is not None:
662
+ stmt = self.stmt_where_str(stmt, sensor_name, FlarmRaw.sensorname)
663
+
664
+ for condition in args:
665
+ stmt = stmt.where(condition)
666
+
667
+ stmt = stmt.where(
668
+ FlarmRaw.timestamp >= start_ts,
669
+ FlarmRaw.timestamp <= stop_ts,
670
+ FlarmRaw.hour >= start_ts.floor("1h"),
671
+ FlarmRaw.hour < stop_ts.ceil("1h"),
573
672
  )
574
673
 
575
674
  if limit is not None:
@@ -712,7 +811,7 @@ class Trino(OpenSkyDBAPI):
712
811
  )
713
812
  .where(
714
813
  FlightsData4.day >= start_ts.floor("1d"),
715
- FlightsData4.day <= start_ts.ceil("1d"),
814
+ FlightsData4.day <= stop_ts.ceil("1d"),
716
815
  )
717
816
  )
718
817
 
@@ -766,8 +865,8 @@ class Trino(OpenSkyDBAPI):
766
865
  )
767
866
  .group_by(StateVectorsData4.icao24)
768
867
  .where(
769
- StateVectorsData4.hour >= start_ts.floor("1H"),
770
- StateVectorsData4.hour <= stop_ts.ceil("1H"),
868
+ StateVectorsData4.hour >= start_ts.floor("1h"),
869
+ StateVectorsData4.hour <= stop_ts.ceil("1h"),
771
870
  StateVectorsData4.time >= start_ts,
772
871
  StateVectorsData4.time <= stop_ts,
773
872
  )
@@ -819,8 +918,8 @@ class Trino(OpenSkyDBAPI):
819
918
  stmt = stmt.where(
820
919
  Table.mintime >= start_ts,
821
920
  Table.mintime <= stop_ts,
822
- Table.hour >= start_ts.floor("1H"),
823
- Table.hour < stop_ts.ceil("1H"),
921
+ Table.hour >= start_ts.floor("1h"),
922
+ Table.hour < stop_ts.ceil("1h"),
824
923
  )
825
924
 
826
925
  if limit is not None:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes