oshconnect 0.2.0__py3-none-any.whl
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.
- oshconnect/__init__.py +9 -0
- oshconnect/control.py +65 -0
- oshconnect/core_datamodels.py +160 -0
- oshconnect/datasource.py +569 -0
- oshconnect/datastore.py +10 -0
- oshconnect/osh_connect_datamodels.py +346 -0
- oshconnect/oshconnectapi.py +272 -0
- oshconnect/styling.py +37 -0
- oshconnect/timemanagement.py +425 -0
- oshconnect-0.2.0.dist-info/LICENSE +373 -0
- oshconnect-0.2.0.dist-info/METADATA +27 -0
- oshconnect-0.2.0.dist-info/RECORD +13 -0
- oshconnect-0.2.0.dist-info/WHEEL +4 -0
oshconnect/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright (c) 2024 Botts Innovative Research, Inc.
|
|
3
|
+
# Date: 2024/5/28
|
|
4
|
+
# Author: Ian Patterson
|
|
5
|
+
# Contact Email: ian@botts-inc.com
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
|
|
8
|
+
class Example:
|
|
9
|
+
pass
|
oshconnect/control.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright (c) 2024 Botts Innovative Research, Inc.
|
|
3
|
+
# Date: 2024/7/1
|
|
4
|
+
# Author: Ian Patterson
|
|
5
|
+
# Contact Email: ian@botts-inc.com
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
import websockets
|
|
8
|
+
from conSys4Py.comm.mqtt import MQTTCommClient
|
|
9
|
+
from conSys4Py.datamodels.commands import CommandJSON
|
|
10
|
+
from conSys4Py.datamodels.control_streams import ControlStreamJSONSchema
|
|
11
|
+
|
|
12
|
+
from oshconnect.osh_connect_datamodels import System
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ControlSchema:
|
|
16
|
+
schema: dict = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ControlStream:
|
|
20
|
+
name: str = None
|
|
21
|
+
_parent_systems: System = None
|
|
22
|
+
_strategy: str = "mqtt"
|
|
23
|
+
_resource_endpoint = None
|
|
24
|
+
# _auth: str = None
|
|
25
|
+
_websocket: websockets.WebSocketServerProtocol = None
|
|
26
|
+
_schema: ControlStreamJSONSchema = None
|
|
27
|
+
_mqtt_client: MQTTCommClient = None
|
|
28
|
+
|
|
29
|
+
def __init__(self, parent_system: System, resource_endpoint: str, name=None, strategy="mqtt"):
|
|
30
|
+
self._parent_systems = parent_system
|
|
31
|
+
self.name = name
|
|
32
|
+
self._strategy = strategy
|
|
33
|
+
self._resource_endpoint = resource_endpoint
|
|
34
|
+
|
|
35
|
+
def set_schema(self, schema: ControlStreamJSONSchema):
|
|
36
|
+
self._schema = schema
|
|
37
|
+
|
|
38
|
+
def connect(self):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def subscribe(self):
|
|
42
|
+
if self._strategy == "mqtt" and self._mqtt_client is not None:
|
|
43
|
+
self._mqtt_client.subscribe(f'{self._resource_endpoint}/commands')
|
|
44
|
+
elif self._strategy == "mqtt" and self._mqtt_client is None:
|
|
45
|
+
raise ValueError("No MQTT Client found.")
|
|
46
|
+
elif self._strategy == "websocket":
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
def publish(self, payload: CommandJSON):
|
|
50
|
+
if self._strategy == "mqtt" and self._mqtt_client is not None:
|
|
51
|
+
self._mqtt_client.publish(f'{self._resource_endpoint}/status', payload=payload, qos=1)
|
|
52
|
+
elif self._strategy == "mqtt" and self._mqtt_client is None:
|
|
53
|
+
raise ValueError("No MQTT Client found.")
|
|
54
|
+
elif self._strategy == "websocket":
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
def disconnect(self):
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
def unsubscribe(self):
|
|
61
|
+
self._mqtt_client.unsubscribe(f'{self._resource_endpoint}/commands')
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Command:
|
|
65
|
+
pass
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright (c) 2024 Botts Innovative Research, Inc.
|
|
3
|
+
# Date: 2024/6/26
|
|
4
|
+
# Author: Ian Patterson
|
|
5
|
+
# Contact Email: ian@botts-inc.com
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
from conSys4Py.datamodels.swe_components import Geometry
|
|
12
|
+
from conSys4Py.datamodels.datastreams import DatastreamSchema
|
|
13
|
+
from conSys4Py.datamodels.api_utils import Link
|
|
14
|
+
from pydantic import BaseModel, ConfigDict, Field, SerializeAsAny
|
|
15
|
+
from shapely import Point
|
|
16
|
+
|
|
17
|
+
from oshconnect.timemanagement import DateTimeSchema, TimePeriod
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BoundingBox(BaseModel):
|
|
21
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
22
|
+
|
|
23
|
+
lower_left_corner: Point = Field(..., description="The lower left corner of the bounding box.")
|
|
24
|
+
upper_right_corner: Point = Field(..., description="The upper right corner of the bounding box.")
|
|
25
|
+
min_value: float = Field(None, description="The minimum value of the bounding box.")
|
|
26
|
+
max_value: float = Field(None, description="The maximum value of the bounding box.")
|
|
27
|
+
|
|
28
|
+
# @model_validator(mode='before')
|
|
29
|
+
# def validate_minmax(self) -> Self:
|
|
30
|
+
# if self.min_value > self.max_value:
|
|
31
|
+
# raise ValueError("min_value must be less than max_value")
|
|
32
|
+
# return self
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SecurityConstraints:
|
|
36
|
+
constraints: list
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class LegalConstraints:
|
|
40
|
+
constraints: list
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Characteristics:
|
|
44
|
+
characteristics: list
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Capabilities:
|
|
48
|
+
capabilities: list
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Contact:
|
|
52
|
+
contact: list
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class Documentation:
|
|
56
|
+
documentation: list
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class HistoryEvent:
|
|
60
|
+
history_event: list
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ConfigurationSettings:
|
|
64
|
+
settings: list
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class FeatureOfInterest:
|
|
68
|
+
feature: list
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Input:
|
|
72
|
+
input: list
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Output:
|
|
76
|
+
output: list
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class Parameter:
|
|
80
|
+
parameter: list
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Mode:
|
|
84
|
+
mode: list
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ProcessMethod:
|
|
88
|
+
method: list
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class SystemResource(BaseModel):
|
|
92
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
93
|
+
|
|
94
|
+
feature_type: str = Field(None, serialization_alias="type")
|
|
95
|
+
system_id: str = Field(None, serialization_alias="id")
|
|
96
|
+
properties: dict = Field(None)
|
|
97
|
+
geometry: Geometry | None = Field(None)
|
|
98
|
+
bbox: BoundingBox = Field(None)
|
|
99
|
+
links: List[Link] = Field(None)
|
|
100
|
+
description: str = Field(None)
|
|
101
|
+
uid: str = Field(None, serialization_alias="uniqueId")
|
|
102
|
+
label: str = Field(None)
|
|
103
|
+
lang: str = Field(None)
|
|
104
|
+
keywords: List[str] = Field(None)
|
|
105
|
+
identifiers: List[str] = Field(None)
|
|
106
|
+
classifiers: List[str] = Field(None)
|
|
107
|
+
valid_time: DateTimeSchema = Field(None, serialization_alias="validTime")
|
|
108
|
+
security_constraints: List[SecurityConstraints] = Field(None, serialization_alias="securityConstraints")
|
|
109
|
+
legal_constraints: List[LegalConstraints] = Field(None, serialization_alias="legalConstraints")
|
|
110
|
+
characteristics: List[Characteristics] = Field(None)
|
|
111
|
+
capabilities: List[Capabilities] = Field(None)
|
|
112
|
+
contacts: List[Contact] = Field(None)
|
|
113
|
+
documentation: List[Documentation] = Field(None)
|
|
114
|
+
history: List[HistoryEvent] = Field(None)
|
|
115
|
+
definition: str = Field(None)
|
|
116
|
+
type_of: str = Field(None, serialization_alias="typeOf")
|
|
117
|
+
configuration: ConfigurationSettings = Field(None)
|
|
118
|
+
features_of_interest: List[FeatureOfInterest] = Field(None, serialization_alias="featuresOfInterest")
|
|
119
|
+
inputs: List[Input] = Field(None)
|
|
120
|
+
outputs: List[Output] = Field(None)
|
|
121
|
+
parameters: List[Parameter] = Field(None)
|
|
122
|
+
modes: List[Mode] = Field(None)
|
|
123
|
+
method: ProcessMethod = Field(None)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class DatastreamResource(BaseModel):
|
|
127
|
+
"""
|
|
128
|
+
The DatastreamResource class is a Pydantic model that represents a datastream resource in the OGC SensorThings API.
|
|
129
|
+
It contains all the necessary and optional properties listed in the OGC Connected Systems API documentation. Note
|
|
130
|
+
that, depending on the format of the request, the fields needed may differ. There may be derived models in a later
|
|
131
|
+
release that will have different sets of required fields to ease the validation process for users.
|
|
132
|
+
"""
|
|
133
|
+
# model_config = ConfigDict(populate_by_name=True)
|
|
134
|
+
|
|
135
|
+
ds_id: str = Field(..., serialization_alias="id")
|
|
136
|
+
name: str = Field(...)
|
|
137
|
+
description: str = Field(None)
|
|
138
|
+
valid_time: TimePeriod = Field(..., serialization_alias="validTime")
|
|
139
|
+
output_name: str = Field(None, serialization_alias="outputName")
|
|
140
|
+
procedure_link: Link = Field(None, serialization_alias="procedureLink@link")
|
|
141
|
+
deployment_link: Link = Field(None, serialization_alias="deploymentLink@link")
|
|
142
|
+
ultimate_feature_of_interest_link: Link = Field(None, serialization_alias="ultimateFeatureOfInterest@link")
|
|
143
|
+
sampling_feature_link: Link = Field(None, serialization_alias="samplingFeature@link")
|
|
144
|
+
parameters: dict = Field(None)
|
|
145
|
+
phenomenon_time: TimePeriod = Field(None, serialization_alias="phenomenonTimeInterval")
|
|
146
|
+
result_time: TimePeriod = Field(None, serialization_alias="resultTimeInterval")
|
|
147
|
+
ds_type: str = Field(None, serialization_alias="type")
|
|
148
|
+
result_type: str = Field(None, serialization_alias="resultType")
|
|
149
|
+
links: List[Link] = Field(None)
|
|
150
|
+
record_schema: SerializeAsAny[DatastreamSchema] = Field(None, serialization_alias="schema")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class ObservationResource(BaseModel):
|
|
154
|
+
sampling_feature_id: str = Field(None, serialization_alias="samplingFeature@Id")
|
|
155
|
+
procedure_link: Link = Field(None, serialization_alias="procedure@link")
|
|
156
|
+
phenomenon_time: DateTimeSchema = Field(None, serialization_alias="phenomenonTime")
|
|
157
|
+
result_time: DateTimeSchema = Field(..., serialization_alias="resultTime")
|
|
158
|
+
parameters: dict = Field(None)
|
|
159
|
+
result: dict = Field(...)
|
|
160
|
+
result_link: Link = Field(None, serialization_alias="result@link")
|