frost-sta-client 1.1.50__tar.gz → 1.1.51__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.
Files changed (64) hide show
  1. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/PKG-INFO +1 -1
  2. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/__version__.py +1 -1
  3. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/datastream.py +1 -1
  4. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/ext/data_array_document.py +67 -68
  5. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/ext/entity_list.py +169 -162
  6. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/multi_datastream.py +345 -345
  7. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/observedproperty.py +210 -210
  8. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client.egg-info/PKG-INFO +1 -1
  9. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client.egg-info/SOURCES.txt +9 -1
  10. frost_sta_client-1.1.51/tests/test_dao_base.py +71 -0
  11. frost_sta_client-1.1.51/tests/test_entity_behaviour.py +21 -0
  12. frost_sta_client-1.1.51/tests/test_entity_list.py +50 -0
  13. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/tests/test_entity_reader.py +266 -267
  14. frost_sta_client-1.1.51/tests/test_ext_data_array.py +20 -0
  15. frost_sta_client-1.1.51/tests/test_ext_entity_type.py +7 -0
  16. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/tests/test_integration.py +2 -0
  17. frost_sta_client-1.1.51/tests/test_query_unit.py +42 -0
  18. frost_sta_client-1.1.51/tests/test_service_unit.py +58 -0
  19. frost_sta_client-1.1.51/tests/test_utils_more.py +33 -0
  20. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/LICENSE +0 -0
  21. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/README.md +0 -0
  22. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/__init__.py +0 -0
  23. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/__init__.py +0 -0
  24. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/actuator.py +0 -0
  25. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/base.py +0 -0
  26. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/datastream.py +0 -0
  27. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/features_of_interest.py +0 -0
  28. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/historical_location.py +0 -0
  29. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/location.py +0 -0
  30. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/multi_datastream.py +0 -0
  31. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/observation.py +0 -0
  32. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/observedproperty.py +0 -0
  33. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/sensor.py +0 -0
  34. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/task.py +0 -0
  35. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/tasking_capability.py +0 -0
  36. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/dao/thing.py +0 -0
  37. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/__init__.py +0 -0
  38. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/actuator.py +0 -0
  39. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/entity.py +0 -0
  40. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/ext/__init__.py +0 -0
  41. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/ext/data_array_value.py +0 -0
  42. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/ext/entity_type.py +0 -0
  43. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/ext/unitofmeasurement.py +0 -0
  44. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/feature_of_interest.py +0 -0
  45. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/historical_location.py +0 -0
  46. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/location.py +0 -0
  47. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/observation.py +0 -0
  48. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/sensor.py +0 -0
  49. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/task.py +0 -0
  50. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/tasking_capability.py +0 -0
  51. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/model/thing.py +0 -0
  52. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/query/__init__.py +0 -0
  53. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/query/query.py +0 -0
  54. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/service/__init__.py +0 -0
  55. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/service/auth_handler.py +0 -0
  56. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/service/sensorthingsservice.py +0 -0
  57. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client/utils.py +0 -0
  58. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client.egg-info/dependency_links.txt +0 -0
  59. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client.egg-info/requires.txt +0 -0
  60. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/frost_sta_client.egg-info/top_level.txt +0 -0
  61. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/setup.cfg +0 -0
  62. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/setup.py +0 -0
  63. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/tests/test_entity_formatter.py +0 -0
  64. {frost_sta_client-1.1.50 → frost_sta_client-1.1.51}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frost_sta_client
3
- Version: 1.1.50
3
+ Version: 1.1.51
4
4
  Summary: a client library to facilitate interaction with a FROST SensorThingsAPI Server
5
5
  Home-page: https://github.com/FraunhoferIOSB/FROST-Python-Client
6
6
  Author: Fraunhofer IOSB
@@ -1,5 +1,5 @@
1
1
  __title__ = 'frost_sta_client'
2
- __version__ = '1.1.50'
2
+ __version__ = '1.1.51'
3
3
  __license__ = 'LGPL3'
4
4
  __author__ = 'Fraunhofer IOSB'
5
5
  __copyright__ = 'Fraunhofer IOSB'
@@ -146,7 +146,7 @@ class Datastream(entity.Entity):
146
146
  @observed_area.setter
147
147
  def observed_area(self, value):
148
148
  if value is None:
149
- self._location = None
149
+ self._observed_area = None
150
150
  return
151
151
  geo_classes = [obj for _, obj in inspect.getmembers(geojson) if inspect.isclass(obj) and
152
152
  obj.__module__ == 'geojson.geometry']
@@ -1,68 +1,67 @@
1
- # Copyright (C) 2021 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
2
- # Karlsruhe, Germany.
3
- #
4
- # This program is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU Lesser General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU Lesser General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU Lesser General Public License
15
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- from .data_array_value import DataArrayValue
17
-
18
-
19
- class DataArrayDocument:
20
- def __init__(self, count=-1, next_link = None, value=None):
21
- if value is None:
22
- value = []
23
- self._count = count
24
- self._next_link = next_link
25
- self._value = value
26
-
27
- @property
28
- def count(self):
29
- return self._count
30
-
31
- @count.setter
32
- def count(self, value):
33
- if type(value) == int or value is None:
34
- self._count = value
35
- else:
36
- raise TypeError('count should be of type int')
37
-
38
- @property
39
- def next_link(self):
40
- return self._next_link
41
-
42
- @next_link.setter
43
- def next_link(self, value):
44
- if type(value) == str or value is None:
45
- self._next_link = value
46
- else:
47
- raise TypeError('nextLink should be of type str')
48
-
49
- @property
50
- def value(self):
51
- return self._value
52
-
53
- @value.setter
54
- def value(self, value):
55
- if type(value) == list and all(isinstance(x, DataArrayValue) for x in value):
56
- self._value = value
57
- else:
58
- raise TypeError('value should be a list of type DataArrayValue')
59
-
60
- def get_observations(self):
61
- obs_list = []
62
- for dav in self.value:
63
- obs_list.concat(dav.get_observations())
64
- return obs_list
65
-
66
- def add_data_array_value(self, dav):
67
- self.value.append(dav)
68
-
1
+ # Copyright (C) 2021 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
2
+ # Karlsruhe, Germany.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Lesser General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ from .data_array_value import DataArrayValue
17
+
18
+
19
+ class DataArrayDocument:
20
+ def __init__(self, count=-1, next_link = None, value=None):
21
+ if value is None:
22
+ value = []
23
+ self._count = count
24
+ self._next_link = next_link
25
+ self._value = value
26
+
27
+ @property
28
+ def count(self):
29
+ return self._count
30
+
31
+ @count.setter
32
+ def count(self, value):
33
+ if type(value) == int or value is None:
34
+ self._count = value
35
+ else:
36
+ raise TypeError('count should be of type int')
37
+
38
+ @property
39
+ def next_link(self):
40
+ return self._next_link
41
+
42
+ @next_link.setter
43
+ def next_link(self, value):
44
+ if type(value) == str or value is None:
45
+ self._next_link = value
46
+ else:
47
+ raise TypeError('nextLink should be of type str')
48
+
49
+ @property
50
+ def value(self):
51
+ return self._value
52
+
53
+ @value.setter
54
+ def value(self, value):
55
+ if type(value) == list and all(isinstance(x, DataArrayValue) for x in value):
56
+ self._value = value
57
+ else:
58
+ raise TypeError('value should be a list of type DataArrayValue')
59
+
60
+ def get_observations(self):
61
+ obs_list = []
62
+ for dav in self.value:
63
+ obs_list.extend(dav.observations)
64
+ return obs_list
65
+
66
+ def add_data_array_value(self, dav):
67
+ self.value.append(dav)
@@ -1,162 +1,169 @@
1
- # Copyright (C) 2021 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
2
- # Karlsruhe, Germany.
3
- #
4
- # This program is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU Lesser General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU Lesser General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU Lesser General Public License
15
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
-
17
- import logging
18
- import requests
19
- import frost_sta_client
20
-
21
-
22
- class EntityList:
23
- def __init__(self, entity_class, entities=None):
24
- if entities is None:
25
- entities = []
26
- self.entities = entities
27
- self.entity_class = entity_class
28
- self.next_link = None
29
- self.service = None
30
- self.iterable_entities = None
31
- self.count = None
32
- self.callback = None
33
- self.step_size = None
34
-
35
- def __new__(cls, *args, **kwargs):
36
- new_entity_list = super().__new__(cls)
37
- attributes = {'_entities': None, '_entity_class': '', '_next_link': '', '_service': {}, '_count': '',
38
- '_iterable_entities': None, '_callback': None,
39
- '_step_size': None}
40
- for key, value in attributes.items():
41
- new_entity_list.__dict__[key] = value
42
- return new_entity_list
43
-
44
- def __iter__(self):
45
- self.iterable_entities = iter(enumerate(self.entities))
46
- return self
47
-
48
- def __next__(self):
49
- idx, next_entity = next(self.iterable_entities, (len(self.entities), None))
50
- if self.step_size is not None and idx is not None and idx % self.step_size == 0:
51
- self.callback(idx)
52
- if next_entity is not None:
53
- return next_entity
54
- if self.next_link is not None:
55
- try:
56
- response = self.service.execute('get', self.next_link)
57
- except requests.exceptions.HTTPError as e:
58
- error_json = e.response.json()
59
- error_message = error_json['message']
60
- logging.error("Query failed with status-code {}, {}".format(e.response.status_code, error_message))
61
- raise e
62
- logging.debug('Received response: {} from {}'.format(response.status_code, self.next_link))
63
- try:
64
- json_response = response.json()
65
- except ValueError:
66
- raise ValueError('Cannot find json in http response')
67
-
68
- result_list = frost_sta_client.utils.transform_json_to_entity_list(json_response, self.entity_class)
69
- self.entities += result_list.entities
70
- self.set_service(self.service)
71
- self.next_link = json_response.get("@iot.nextLink", None)
72
- self.iterable_entities = iter(enumerate(self.entities[-len(result_list.entities):], start=idx))
73
- return next(self.iterable_entities)[1]
74
- raise StopIteration
75
-
76
- def get(self, index):
77
- if not isinstance(index, int):
78
- raise IndexError('index must be an integer')
79
- if index >= len(self.entities):
80
- raise IndexError('index exceeds total number of entities')
81
- if index < 0:
82
- raise IndexError('negative indices cannot be accessed')
83
- return self.entities[index]
84
-
85
- @property
86
- def entity_class(self):
87
- return self._entity_class
88
-
89
- @entity_class.setter
90
- def entity_class(self, value):
91
- if isinstance(value, str):
92
- self._entity_class = value
93
- return
94
- raise ValueError('entity_class should be of type str')
95
-
96
- @property
97
- def entities(self):
98
- return self._entities
99
-
100
- @entities.setter
101
- def entities(self, values):
102
- if isinstance(values, list) and all(isinstance(v, frost_sta_client.model.entity.Entity) for v in values):
103
- self._entities = values
104
- return
105
- raise ValueError('entities should be a list of entities')
106
-
107
- @property
108
- def callback(self):
109
- return self._callback
110
-
111
- @callback.setter
112
- def callback(self, callback):
113
- if callable(callback) or callback is None:
114
- self._callback = callback
115
-
116
- @property
117
- def step_size(self):
118
- return self._step_size
119
-
120
- @step_size.setter
121
- def step_size(self, value):
122
- if isinstance(value, int) or value is None:
123
- self._step_size = value
124
- return
125
- raise ValueError('step_size should be of type int')
126
-
127
- @property
128
- def next_link(self):
129
- return self._next_link
130
-
131
- @next_link.setter
132
- def next_link(self, value):
133
- if value is None or isinstance(value, str):
134
- self._next_link = value
135
- return
136
- raise ValueError('next_link should be of type string')
137
-
138
- @property
139
- def service(self):
140
- return self._service
141
-
142
- @service.setter
143
- def service(self, value):
144
- if value is None or isinstance(value, frost_sta_client.service.sensorthingsservice.SensorThingsService):
145
- self._service = value
146
- return
147
- raise ValueError('service should be of type SensorThingsService')
148
-
149
- def set_service(self, service):
150
- self.service = service
151
- for entity in self.entities:
152
- entity.set_service(service)
153
-
154
- def __getstate__(self):
155
- data = []
156
- for entity in self.entities:
157
- data.append(entity.__getstate__())
158
- return data
159
-
160
- def __setstate__(self, state):
161
- self._next_link = state.get(self.entities + '@nextLink')
162
- pass
1
+ # Copyright (C) 2021 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
2
+ # Karlsruhe, Germany.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Lesser General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ import logging
18
+ import requests
19
+ import frost_sta_client
20
+
21
+
22
+ class EntityList:
23
+ def __init__(self, entity_class, entities=None):
24
+ if entities is None:
25
+ entities = []
26
+ self.entities = entities
27
+ self.entity_class = entity_class
28
+ self.next_link = None
29
+ self.service = None
30
+ self.iterable_entities = None
31
+ self.count = None
32
+ self.callback = None
33
+ self.step_size = None
34
+
35
+ def __new__(cls, *args, **kwargs):
36
+ new_entity_list = super().__new__(cls)
37
+ attributes = {'_entities': None, '_entity_class': '', '_next_link': '', '_service': {}, '_count': '',
38
+ '_iterable_entities': None, '_callback': None,
39
+ '_step_size': None}
40
+ for key, value in attributes.items():
41
+ new_entity_list.__dict__[key] = value
42
+ return new_entity_list
43
+
44
+ def __iter__(self):
45
+ self.iterable_entities = iter(enumerate(self.entities))
46
+ return self
47
+
48
+ def __next__(self):
49
+ idx, next_entity = next(self.iterable_entities, (None, None))
50
+ # Only trigger callback when returning a real entity, not on sentinel indices
51
+ if next_entity is None:
52
+ # If current page is exhausted, try to load the next page
53
+ if self.next_link is None:
54
+ raise StopIteration
55
+ try:
56
+ response = self.service.execute('get', self.next_link)
57
+ except requests.exceptions.HTTPError as e:
58
+ error_json = e.response.json()
59
+ error_message = error_json['message']
60
+ logging.error("Query failed with status-code {}, {}".format(e.response.status_code, error_message))
61
+ raise e
62
+ logging.debug('Received response: {} from {}'.format(response.status_code, self.next_link))
63
+ try:
64
+ json_response = response.json()
65
+ except ValueError:
66
+ raise ValueError('Cannot find json in http response')
67
+
68
+ result_list = frost_sta_client.utils.transform_json_to_entity_list(json_response, self.entity_class)
69
+ # Append new entities and reset iterator to iterate over the newly fetched page
70
+ start_index = len(self.entities)
71
+ self.entities += result_list.entities
72
+ self.set_service(self.service)
73
+ self.next_link = json_response.get("@iot.nextLink", None)
74
+ self.iterable_entities = iter(enumerate(self.entities[start_index:], start=start_index))
75
+ idx, next_entity = next(self.iterable_entities, (None, None))
76
+ if next_entity is None:
77
+ raise StopIteration
78
+ if self.step_size is not None and self.callback is not None and idx % self.step_size == 0:
79
+ self.callback(idx)
80
+ return next_entity
81
+ raise StopIteration
82
+
83
+ def get(self, index):
84
+ if not isinstance(index, int):
85
+ raise IndexError('index must be an integer')
86
+ if index >= len(self.entities):
87
+ raise IndexError('index exceeds total number of entities')
88
+ if index < 0:
89
+ raise IndexError('negative indices cannot be accessed')
90
+ return self.entities[index]
91
+
92
+ @property
93
+ def entity_class(self):
94
+ return self._entity_class
95
+
96
+ @entity_class.setter
97
+ def entity_class(self, value):
98
+ if isinstance(value, str):
99
+ self._entity_class = value
100
+ return
101
+ raise ValueError('entity_class should be of type str')
102
+
103
+ @property
104
+ def entities(self):
105
+ return self._entities
106
+
107
+ @entities.setter
108
+ def entities(self, values):
109
+ if isinstance(values, list) and all(isinstance(v, frost_sta_client.model.entity.Entity) for v in values):
110
+ self._entities = values
111
+ return
112
+ raise ValueError('entities should be a list of entities')
113
+
114
+ @property
115
+ def callback(self):
116
+ return self._callback
117
+
118
+ @callback.setter
119
+ def callback(self, callback):
120
+ if callable(callback) or callback is None:
121
+ self._callback = callback
122
+
123
+ @property
124
+ def step_size(self):
125
+ return self._step_size
126
+
127
+ @step_size.setter
128
+ def step_size(self, value):
129
+ if isinstance(value, int) or value is None:
130
+ self._step_size = value
131
+ return
132
+ raise ValueError('step_size should be of type int')
133
+
134
+ @property
135
+ def next_link(self):
136
+ return self._next_link
137
+
138
+ @next_link.setter
139
+ def next_link(self, value):
140
+ if value is None or isinstance(value, str):
141
+ self._next_link = value
142
+ return
143
+ raise ValueError('next_link should be of type string')
144
+
145
+ @property
146
+ def service(self):
147
+ return self._service
148
+
149
+ @service.setter
150
+ def service(self, value):
151
+ if value is None or isinstance(value, frost_sta_client.service.sensorthingsservice.SensorThingsService):
152
+ self._service = value
153
+ return
154
+ raise ValueError('service should be of type SensorThingsService')
155
+
156
+ def set_service(self, service):
157
+ self.service = service
158
+ for entity in self.entities:
159
+ entity.set_service(service)
160
+
161
+ def __getstate__(self):
162
+ data = []
163
+ for entity in self.entities:
164
+ data.append(entity.__getstate__())
165
+ return data
166
+
167
+ def __setstate__(self, state):
168
+ self._next_link = state.get(self.entities + '@nextLink')
169
+ pass