Skip to content

Commit 84cb505

Browse files
committed
feat: include how description
1 parent 05db63e commit 84cb505

File tree

5 files changed

+92
-13
lines changed

5 files changed

+92
-13
lines changed

CoT/convert/ais.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import datetime
2+
from CoT.models.core import Event, Point
3+
4+
def FromAIS(data: bytes) -> Event:
5+
try:
6+
import pyais
7+
_pyais_available = True
8+
except ImportError:
9+
_pyais_available = False
10+
11+
if not _pyais_available:
12+
raise ImportError("The 'pyais' library is required for FromAIS but is not installed. Install it with: pip install pycot[ais]")
13+
14+
ais_decoded = pyais.decode(data)
15+
ais_dict = ais_decoded.asdict()
16+
17+
now = datetime.datetime.now(datetime.timezone.utc)
18+
stale = now + datetime.timedelta(minutes=2)
19+
20+
return Event(
21+
version="2.0",
22+
type="a-u-S-X-M",
23+
access="Undefined",
24+
uid="MMSI-{}".format(ais_dict['MetaData']['MMSI']),
25+
time=now,
26+
start=now,
27+
stale=stale,
28+
how="m-f",
29+
qos="2-i-c",
30+
point=Point(lat=float(ais_dict["Message"]["PositionReport"]["Latitude"]), lon=float(ais_dict["Message"]["PositionReport"]["Longitude"]), hae=9999999, ce=9999999, le=9999999),
31+
detail={"contact": {"callsign": ais_dict["MetaData"]["ShipName"]}},
32+
)
33+
34+
def FromGeoJSON(dict) -> Event:
35+
pass

CoT/models/core.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@
33
from datetime import datetime
44
from typing import Optional, Any
55

6-
from pydantic import ConfigDict, Field, GetCoreSchemaHandler, computed_field
6+
from pydantic import ConfigDict, Field, GetCoreSchemaHandler, computed_field, constr
77
from pydantic_core import CoreSchema, core_schema
8-
98
from CoT.utils import CustomModel
109
from CoT.xml import unparse
11-
from CoT.types import CoTTypes, CoTReservations
12-
10+
from CoT.types import CoTTypes, CoTReservations, CoTHow
11+
from pydantic import BaseModel
12+
KeywordsPattern = constr(pattern=r"^[\w\- ]+(,[\w\- ]+)*$")
1313

14+
class Remarks(BaseModel):
15+
text: str
16+
1417
# MITRE Definition does not have addition subschema
1518
class Detail(CustomModel):
16-
model_config = ConfigDict(extra="allow")
17-
19+
model_config = ConfigDict(extras=True, populate_by_name=True)
20+
remarks: Remarks = Optional[Remarks]
1821

1922
class Point(CustomModel):
2023
lat: float = Field(ge=-90, le=90)
@@ -63,7 +66,17 @@ def __get_pydantic_core_schema__(
6366
) -> CoreSchema:
6467
return core_schema.no_info_after_validator_function(cls, handler(str))
6568

66-
69+
70+
class How(str):
71+
value: str
72+
73+
@computed_field
74+
@property
75+
def description(self) -> str:
76+
if self.value not in CoTHow:
77+
return "Unknown"
78+
79+
return CoTHow[self.value]
6780

6881
class Event(CustomModel):
6982
version: float = 2.0
@@ -72,7 +85,7 @@ class Event(CustomModel):
7285
time: datetime
7386
start: datetime
7487
stale: datetime
75-
how: str = Field(pattern=r"\w-\w")
88+
how: How = Field(pattern=r"\w-\w")
7689
opex: Optional[str] = None
7790
qos: Optional[str] = None
7891
access: Optional[str] = None

CoT/types.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4034,3 +4034,35 @@
40344034
"desc": "Other",
40354035
},
40364036
}
4037+
4038+
# https://github.com/FreeTAKTeam/FreeTakServer/blob/master/FreeTAKServer/model/RestMessages/RestEnumerations.py#L199-L230
4039+
4040+
CoTHow = {
4041+
"m-i": "mensurated",
4042+
"h-t": "transcribed",
4043+
"m-": "machine",
4044+
"m-g": "gps",
4045+
"h-g-i-g-o": "gigo",
4046+
"a-f-G-E-V-9-1-1": "mayday",
4047+
"h-e": "estimated",
4048+
"h-c": "calculated",
4049+
"h-p": "pasted",
4050+
"m-m": "magnetic",
4051+
"m-n": "ins",
4052+
"m-s": "simulated",
4053+
"m-c": "configured",
4054+
"m-r": "radio",
4055+
"m-p": "propagated",
4056+
"m-f": "fused",
4057+
"m-a": "tracker",
4058+
"m-g-n": "ins+gps",
4059+
"m-g-d": "dgps",
4060+
"m-r-e": "eplrs",
4061+
"m-r-p": "plrs",
4062+
"m-r-d": "doppler",
4063+
"m-r-v": "vhf",
4064+
"m-r-t": "tadil",
4065+
"m-r-t-a": "tadila",
4066+
"m-r-t-b": "tadilb",
4067+
"m-r-t-j": "tadilj"
4068+
}

CoT/utils.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@
1212

1313

1414
class CustomModel(BaseModel):
15-
# -W ignore::pydantic.warnings.PydanticDeprecatedSince20
16-
model_config = ConfigDict(
17-
populate_by_name=True,
18-
)
15+
model_config = ConfigDict(populate_by_name=True)
1916

2017
@model_serializer(mode="wrap")
2118
def serialize(
@@ -43,15 +40,17 @@ def serialize(
4340
def deep_prefix_add(self, obj, prefix="@"):
4441
second_dict = obj.copy()
4542

43+
4644
for key, value in obj.items():
4745
if isinstance(value, dict):
4846
second_dict[key] = CustomModel.deep_prefix_add(value)
4947
continue
5048

5149
if key == "text":
52-
second_dict["#{key}"] = value
50+
second_dict[f'#{key}'] = value
5351
else:
5452
second_dict[f"{prefix}{key}"] = value
5553

5654
del second_dict[key]
55+
print(second_dict)
5756
return second_dict

examples/admin.p12

3.52 KB
Binary file not shown.

0 commit comments

Comments
 (0)