@@ -43,7 +43,8 @@ class Node:
4343 is_secure : bool
4444 _basic_auth : bytes = None
4545 _api_helper : APIHelper
46- _system_ids : list [uuid ] = field (default_factory = list )
46+ # _system_ids: list[uuid] = field(default_factory=list)
47+ _systems : list [System ] = field (default_factory = list )
4748
4849 def __init__ (self , protocol : str , address : str , port : int ,
4950 username : str = None , password : str = None ,
@@ -62,7 +63,7 @@ def __init__(self, protocol: str, address: str, port: int,
6263 password = password )
6364 if self .is_secure :
6465 self ._api_helper .user_auth = True
65- self ._system_ids = []
66+ self ._systems = []
6667
6768 def get_id (self ):
6869 return self ._id
@@ -97,19 +98,38 @@ def discover_systems(self):
9798 system = SystemResource .model_validate (system_json )
9899 sys_obj = System .from_system_resource (system )
99100 sys_obj .update_parent_node (self )
100- self ._system_ids .append (sys_obj . uid )
101+ self ._systems .append (sys_obj )
101102 new_systems .append (sys_obj )
102103 return new_systems
103104 else :
104105 return None
105106
106107 def add_new_system (self , system : System ):
107108 system .update_parent_node (self )
108- self ._system_ids .append (system . uid )
109+ self ._systems .append (system )
109110
110111 def get_api_helper (self ) -> APIHelper :
111112 return self ._api_helper
112113
114+ # System Management
115+
116+ def add_system (self , system : System , target_node : Node , insert_resource : bool = False ):
117+ """
118+ Add a system to the target node.
119+ :param system: System object
120+ :param target_node: Node object
121+ :param insert_resource: Whether to insert the system into the target node's server, default is False
122+ :return:
123+ """
124+ if insert_resource :
125+ system .insert_self ()
126+ target_node .add_new_system (system )
127+ self ._systems .append (system )
128+ return system
129+
130+ def systems (self ) -> list [System ]:
131+ return self ._systems
132+
113133
114134class System :
115135 uid : uuid .UUID
@@ -171,7 +191,8 @@ def from_system_resource(system_resource: SystemResource):
171191 label = other_props ['properties' ]['name' ])
172192 else :
173193 new_system = System (name = system_resource .name ,
174- label = system_resource .label , urn = system_resource .urn , resource_id = system_resource .system_id )
194+ label = system_resource .label , urn = system_resource .urn ,
195+ resource_id = system_resource .system_id )
175196 return new_system
176197
177198 def to_system_resource (self ) -> SystemResource :
@@ -193,19 +214,23 @@ def add_insert_datastream(self, datastream: DataRecordSchema):
193214 print (f'Adding datastream: { datastream .model_dump_json (exclude_none = True , by_alias = True )} ' )
194215 # Make the request to add the datastream
195216 # if successful, add the datastream to the system
196- datastream_schema = SWEDatastreamSchema (record_schema = datastream , obs_format = 'application/swe+json' , encoding = JSONEncoding ())
197- datastream_resource = DatastreamResource (ds_id = "default" , name = datastream .label , output_name = datastream .label , record_schema = datastream_schema ,
217+ datastream_schema = SWEDatastreamSchema (record_schema = datastream , obs_format = 'application/swe+json' ,
218+ encoding = JSONEncoding ())
219+ datastream_resource = DatastreamResource (ds_id = "default" , name = datastream .label , output_name = datastream .label ,
220+ record_schema = datastream_schema ,
198221 valid_time = TimePeriod (start = TimeInstant .now_as_time_instant (),
199- end = TimeInstant (utc_time = TimeUtils .to_utc_time ("2026-12-31T00:00:00Z" ))))
200- # datasource = DataStream(name=datastream.label, datastream=datastream_resource, parent_system=self._sys_resource )
222+ end = TimeInstant (utc_time = TimeUtils .to_utc_time (
223+ "2026-12-31T00:00:00Z" ))) )
201224
202225 api = self ._parent_node .get_api_helper ()
203- print (f'Attempting to create datastream: { datastream_resource .model_dump_json (by_alias = True , exclude_none = True )} ' )
226+ print (
227+ f'Attempting to create datastream: { datastream_resource .model_dump_json (by_alias = True , exclude_none = True )} ' )
204228 print (
205229 f'Attempting to create datastream: { datastream_resource .model_dump (by_alias = True , exclude_none = True )} ' )
206- res = api .create_resource (APIResourceTypes .DATASTREAM , datastream_resource .model_dump_json (by_alias = True , exclude_none = True ),
230+ res = api .create_resource (APIResourceTypes .DATASTREAM ,
231+ datastream_resource .model_dump_json (by_alias = True , exclude_none = True ),
207232 req_headers = {
208- 'Content-Type' : 'application/json'
233+ 'Content-Type' : 'application/json'
209234 }, parent_res_id = self .resource_id )
210235
211236 if res .ok :
@@ -216,10 +241,12 @@ def add_insert_datastream(self, datastream: DataRecordSchema):
216241 raise Exception (f'Failed to create datastream: { datastream_resource .name } ' )
217242
218243 self .datastreams .append (datastream_resource )
244+ return Datastream (datastream_id , self ._parent_node , datastream_resource )
219245
220246 def insert_self (self ):
221247 res = self ._parent_node .get_api_helper ().create_resource (
222- APIResourceTypes .SYSTEM , self .to_system_resource ().model_dump_json (by_alias = True , exclude_none = True ), req_headers = {
248+ APIResourceTypes .SYSTEM , self .to_system_resource ().model_dump_json (by_alias = True , exclude_none = True ),
249+ req_headers = {
223250 'Content-Type' : 'application/sml+json'
224251 })
225252
@@ -232,7 +259,8 @@ def insert_self(self):
232259 def retrieve_resource (self ):
233260 if self .resource_id is None :
234261 return None
235- res = self ._parent_node .get_api_helper ().retrieve_resource (res_type = APIResourceTypes .SYSTEM , res_id = self .resource_id )
262+ res = self ._parent_node .get_api_helper ().retrieve_resource (res_type = APIResourceTypes .SYSTEM ,
263+ res_id = self .resource_id )
236264 if res .ok :
237265 system_json = res .json ()
238266 print (system_json )
@@ -241,31 +269,56 @@ def retrieve_resource(self):
241269 self ._sys_resource = system_resource
242270
243271
244- # class Datastream:
245- # should_poll: bool
246- # _datastream_resource: DatastreamResource
247- #
248- # def __init__(self, datastream_resource: DatastreamResource):
249- # pass
250- #
251- # def get_id(self):
252- # return self._datastream_resource.ds_id
253- #
254- # def insert_observation(self, observation: Observation):
255- # pass
256- #
257- # def to_resource(self) -> DatastreamResource:
258- # # if self._datastream_resource is None:
259- # # self._datastream_resource = DatastreamResource(
260- # # ds_id=uuid.uuid4(), name=self.name,
261- # # valid_time=self.validTimeRange)
262- # return self._datastream_resource
263- #
264- # # def create_from_record_schema(record_schema: DataRecordSchema, parent_system: System):
265- # # new_ds = Datastream(name=record_schema.label, record_schema=record_schema)
266- # # new_ds._datastream_resource = DatastreamResource(ds_id=uuid.uuid4(), name=new_ds.name)
267- # # parent_system.datastreams.append(new_ds)
268- # # return new_ds
272+ class Datastream :
273+ should_poll : bool
274+ _id : str
275+ _datastream_resource : DatastreamResource
276+ _parent_node : Node
277+
278+ def __init__ (self , id : str = None , parent_node : Node = None , datastream_resource : DatastreamResource = None ):
279+ self ._id = id
280+ self ._parent_node = parent_node
281+ self ._datastream_resource = datastream_resource
282+
283+ def get_id (self ):
284+ return self ._datastream_resource .ds_id
285+
286+ def insert_observation (self , observation : Observation ):
287+ pass
288+
289+ def to_resource (self ) -> DatastreamResource :
290+ # if self._datastream_resource is None:
291+ # self._datastream_resource = DatastreamResource(
292+ # ds_id=uuid.uuid4(), name=self.name,
293+ # valid_time=self.validTimeRange)
294+ return self ._datastream_resource
295+
296+ def observation_template (self ) -> Observation :
297+ pass
298+
299+ def create_observation (self , obs_data : dict ):
300+ obs = ObservationResource (result = obs_data , result_time = TimeInstant .now_as_time_instant ())
301+ # Validate against the schema
302+ if self ._datastream_resource .record_schema is not None :
303+ obs .validate_against_schema (self ._datastream_resource .record_schema )
304+ return obs
305+
306+ def insert_observation_dict (self , obs_data : dict ):
307+ res = self ._parent_node .get_api_helper ().create_resource (APIResourceTypes .OBSERVATION , obs_data ,
308+ parent_res_id = self ._id ,
309+ req_headers = {'Content-Type' : 'application/json' })
310+ if res .ok :
311+ obs_id = res .headers ['Location' ].split ('/' )[- 1 ]
312+ print (f'Inserted observation: { obs_id } ' )
313+ return id
314+ else :
315+ raise Exception (f'Failed to insert observation: { res .text } ' )
316+
317+ # def create_from_record_schema(record_schema: DataRecordSchema, parent_system: System):
318+ # new_ds = Datastream(name=record_schema.label, record_schema=record_schema)
319+ # new_ds._datastream_resource = DatastreamResource(ds_id=uuid.uuid4(), name=new_ds.name)
320+ # parent_system.datastreams.append(new_ds)
321+ # return new_ds
269322
270323
271324class ControlChannel :
0 commit comments