1111import websockets
1212from conSys4Py .datamodels .observations import ObservationOMJSONInline
1313
14+ from external_models import TimePeriod
1415from external_models .object_models import DatastreamResource
1516from oshconnect import Utilities
1617from oshconnect .datamodels .datamodels import System
1718from oshconnect .datasource import Mode
19+ from oshconnect import TemporalModes
1820
1921
2022class DataSource :
2123 """
2224 DataSource: represents the active connection of a datastream object
2325 """
2426
25- def __init__ (self , name : str , mode : str , properties : dict , datastream : DatastreamResource , parent_system : System ):
27+ def __init__ (self , name : str , datastream : DatastreamResource , parent_system : System ):
2628 self ._status = None
2729 self ._id = f'datasource-{ uuid4 ()} '
2830 self .name = name
29- self .mode = mode
30- self .properties = properties
3131 self ._datastream = datastream
3232 self ._websocket = None
3333 self ._parent_system = parent_system
34+ self ._playback_mode = None
3435 self ._url = None
35- if mode == "websocket" :
36- self ._url = (f'ws://{ self ._parent_system .get_parent_node ().get_address ()} :'
37- f'{ self ._parent_system .get_parent_node ().get_port ()} '
38- f'/sensorhub/api/datastreams/{ self ._datastream .ds_id } '
39- f'/observations?f=application%2Fjson' )
4036 self ._auth = None
4137 self ._extra_headers = None
4238 if self ._parent_system .get_parent_node ().is_secure :
@@ -63,8 +59,9 @@ def update_properties(self, properties: dict):
6359 # TODO: need to stop in progress sub-processes and restart
6460 self .properties = properties
6561
66- def set_mode (self , mode : str ):
67- self .mode = mode
62+ def set_mode (self , mode : TemporalModes ):
63+ self ._playback_mode = mode
64+ self .generate_url ()
6865
6966 def initialize (self ):
7067 if self ._websocket .is_open ():
@@ -73,14 +70,14 @@ def initialize(self):
7370 self ._status = "initialized"
7471
7572 async def connect (self ):
76- if self .mode == "websocket" :
73+ if self ._playback_mode == TemporalModes . REAL_TIME :
7774 self ._websocket = await websockets .connect (self ._url , extra_headers = self ._extra_headers )
7875 self ._status = "connected"
7976 return self ._websocket
80- elif self .mode == "playback" :
77+ elif self ._playback_mode == TemporalModes . ARCHIVE :
8178 self ._status = "connected"
8279 return "Playback mode is not yet implemented."
83- elif self .mode == "live-batch" :
80+ elif self ._playback_mode == TemporalModes . BATCH :
8481 self ._status = "connected"
8582 return "Live-batch mode is not yet implemented."
8683
@@ -97,16 +94,40 @@ def get_status(self):
9794 def get_ws_client (self ):
9895 return self ._websocket
9996
97+ def is_within_timeperiod (self , timeperiod : TimePeriod ):
98+ return timeperiod .does_timeperiod_overlap (self ._datastream .valid_time )
99+
100+ def generate_url (self ):
101+ if self ._playback_mode == TemporalModes .REAL_TIME :
102+ self ._url = (f'ws://{ self ._parent_system .get_parent_node ().get_address ()} :'
103+ f'{ self ._parent_system .get_parent_node ().get_port ()} '
104+ f'/sensorhub/api/datastreams/{ self ._datastream .ds_id } '
105+ f'/observations?f=application%2Fjson' )
106+ elif self ._playback_mode == TemporalModes .ARCHIVE :
107+ self ._url = (f'ws://{ self ._parent_system .get_parent_node ().get_address ()} :'
108+ f'{ self ._parent_system .get_parent_node ().get_port ()} '
109+ f'/sensorhub/api/datastreams/{ self ._datastream .ds_id } '
110+ f'/observations?f=application%2Fjson&resultTime={ self ._datastream .valid_time .start } /'
111+ f'{ self ._datastream .valid_time .end } ' )
112+ else :
113+ raise ValueError ("Playback mode not set. Cannot generate URL for DataSource." )
114+
100115
101116class DataSourceHandler :
102117 datasource_map : dict [str , DataSource ]
103118 _message_list : MessageHandler
119+ _playback_mode : TemporalModes
104120
105- def __init__ (self ):
121+ def __init__ (self , playback_mode : TemporalModes = TemporalModes . REAL_TIME ):
106122 self .datasource_map = {}
107123 self ._message_list = MessageHandler ()
124+ self ._playback_mode = playback_mode
125+
126+ def set_playback_mode (self , mode : TemporalModes ):
127+ self ._playback_mode = mode
108128
109129 def add_datasource (self , datasource : DataSource ):
130+ datasource .set_mode (self ._playback_mode )
110131 self .datasource_map [datasource .get_id ()] = datasource
111132
112133 def remove_datasource (self , datasource_id : str ):
@@ -120,17 +141,27 @@ def initialize_all(self):
120141 # list comp is faster than for loop
121142 [ds .initialize () for ds in self .datasource_map .values ()]
122143
123- def set_ds_mode (self , mode : str ):
124- var = (ds .set_mode (mode ) for ds in self .datasource_map .values ())
144+ def set_ds_mode (self ):
145+ var = (ds .set_mode (self . _playback_mode ) for ds in self .datasource_map .values ())
125146
126147 async def connect_ds (self , datasource_id : str ):
127148 ds = self .datasource_map .get (datasource_id )
128149 await ds .connect ()
129150
130- async def connect_all (self ):
131- # call connect for all datasources
132- [(ds , await ds .connect ()) for ds in self .datasource_map .values ()]
133- for ds in self .datasource_map .values ():
151+ async def connect_all (self , timeperiod : TimePeriod ):
152+ """
153+ Connects all datasources, optionally within a provided TimePeriod
154+ :param timeperiod:
155+ :return:
156+ """
157+ # search for datasources that fall within the timeperiod
158+ if timeperiod is not None :
159+ ds_matches = [ds for ds in self .datasource_map .values () if ds .is_within_timeperiod (timeperiod )]
160+ else :
161+ ds_matches = self .datasource_map .values ()
162+
163+ [(ds , await ds .connect ()) for ds in ds_matches ]
164+ for ds in ds_matches :
134165 task = asyncio .create_task (self ._handle_datastream_client (ds ))
135166 # return task
136167
0 commit comments