ironflock 1.2.0__tar.gz → 1.2.1__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.
- {ironflock-1.2.0 → ironflock-1.2.1}/PKG-INFO +1 -1
- {ironflock-1.2.0 → ironflock-1.2.1}/pyproject.toml +1 -1
- {ironflock-1.2.0 → ironflock-1.2.1}/src/ironflock/CrossbarConnection.py +10 -10
- {ironflock-1.2.0 → ironflock-1.2.1}/src/ironflock/ironflock.py +68 -40
- {ironflock-1.2.0 → ironflock-1.2.1}/LICENSE +0 -0
- {ironflock-1.2.0 → ironflock-1.2.1}/README.md +0 -0
- {ironflock-1.2.0 → ironflock-1.2.1}/src/ironflock/__init__.py +0 -0
|
@@ -138,7 +138,7 @@ class CrossbarConnection:
|
|
|
138
138
|
self.session = session
|
|
139
139
|
self._is_connected = True
|
|
140
140
|
await self._resubscribe_all()
|
|
141
|
-
print(f"Connection to realm '{session._realm}' established")
|
|
141
|
+
print(f"Connection to IronFlock app realm '{session._realm}' established")
|
|
142
142
|
|
|
143
143
|
if self._first_connection_future and not self._first_connection_future.done():
|
|
144
144
|
self._first_connection_future.set_result(None)
|
|
@@ -147,7 +147,7 @@ class CrossbarConnection:
|
|
|
147
147
|
"""Handle session close event"""
|
|
148
148
|
self.session = None
|
|
149
149
|
self._is_connected = False
|
|
150
|
-
print(f"Connection to realm {self.realm} closed: {details.reason}")
|
|
150
|
+
print(f"Connection to IronFlock app realm {self.realm} closed: {details.reason}")
|
|
151
151
|
|
|
152
152
|
if self._first_connection_future and not self._first_connection_future.done():
|
|
153
153
|
self._first_connection_future.set_exception(
|
|
@@ -158,8 +158,8 @@ class CrossbarConnection:
|
|
|
158
158
|
"""Handle disconnect event"""
|
|
159
159
|
self.session = None
|
|
160
160
|
self._is_connected = False
|
|
161
|
-
print(f"Disconnected from realm {self.realm}, clean: {was_clean}")
|
|
162
|
-
|
|
161
|
+
print(f"Disconnected from IronFlock app realm {self.realm}, clean: {was_clean}")
|
|
162
|
+
|
|
163
163
|
async def _session_wait(self) -> None:
|
|
164
164
|
"""Wait for session to be available"""
|
|
165
165
|
start_time = time.time()
|
|
@@ -177,13 +177,13 @@ class CrossbarConnection:
|
|
|
177
177
|
"""Start the connection"""
|
|
178
178
|
if not self.component:
|
|
179
179
|
raise ValueError("Must call configure() before start()")
|
|
180
|
-
|
|
181
|
-
print(f'Starting connection for realm {self.realm}')
|
|
182
|
-
|
|
183
|
-
# Start the component
|
|
184
|
-
|
|
180
|
+
|
|
181
|
+
print(f'Starting connection for IronFlock app realm {self.realm}')
|
|
182
|
+
|
|
183
|
+
# Start the component (non-blocking in autobahn asyncio)
|
|
184
|
+
self.component.start()
|
|
185
185
|
|
|
186
|
-
# Wait for first connection
|
|
186
|
+
# Wait for first connection to be established
|
|
187
187
|
if self._first_connection_future:
|
|
188
188
|
await self._first_connection_future
|
|
189
189
|
|
|
@@ -3,6 +3,7 @@ import asyncio
|
|
|
3
3
|
from typing import Optional, Any
|
|
4
4
|
|
|
5
5
|
from ironflock.CrossbarConnection import CrossbarConnection, Stage, getSerialNumber
|
|
6
|
+
from autobahn.wamp.types import PublishOptions, RegisterOptions, SubscribeOptions, CallOptions
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class IronFlock:
|
|
@@ -106,8 +107,8 @@ class IronFlock:
|
|
|
106
107
|
# Merge device metadata with user kwargs
|
|
107
108
|
combined_kwargs = {**device_metadata, **kwargs}
|
|
108
109
|
|
|
109
|
-
# Use acknowledged publish
|
|
110
|
-
options =
|
|
110
|
+
# Use acknowledged publish with proper PublishOptions
|
|
111
|
+
options = PublishOptions(acknowledge=True)
|
|
111
112
|
|
|
112
113
|
try:
|
|
113
114
|
pub = await self._connection.publish(
|
|
@@ -159,60 +160,83 @@ class IronFlock:
|
|
|
159
160
|
print(f"Set location failed: {e}")
|
|
160
161
|
return None
|
|
161
162
|
|
|
162
|
-
async def
|
|
163
|
-
"""Registers a function
|
|
164
|
-
|
|
163
|
+
async def register(self, topic: str, endpoint, options: Optional[dict] = None) -> Optional[Any]:
|
|
164
|
+
"""Registers a function with the IronFlock Platform Message Router
|
|
165
|
+
|
|
165
166
|
Args:
|
|
166
|
-
topic (str): The URI of the topic to register
|
|
167
|
-
|
|
167
|
+
topic (str): The URI of the topic to register, e.g. "com.myapp.myprocedure1"
|
|
168
|
+
endpoint: The function to register
|
|
169
|
+
options (dict, optional): Registration options
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Optional[Any]: Object representing a registration
|
|
168
173
|
"""
|
|
169
174
|
if not self.is_connected:
|
|
170
|
-
print("cannot register
|
|
175
|
+
print("cannot register, not connected")
|
|
171
176
|
return None
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
full_topic = f"{swarm_key}.{self._device_key}.{app_key}.{env_value}.{topic}"
|
|
178
|
-
|
|
177
|
+
|
|
178
|
+
# Convert options dict to RegisterOptions if provided
|
|
179
|
+
register_options = RegisterOptions(**options) if options else None
|
|
180
|
+
|
|
179
181
|
try:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
registration = await self._connection.register(full_topic, func)
|
|
183
|
-
return registration
|
|
182
|
+
reg = await self._connection.register(topic, endpoint, options=register_options)
|
|
183
|
+
return reg
|
|
184
184
|
except Exception as e:
|
|
185
|
-
print(f"Register
|
|
185
|
+
print(f"Register failed: {e}")
|
|
186
186
|
return None
|
|
187
187
|
|
|
188
|
-
async def
|
|
189
|
-
"""
|
|
188
|
+
async def subscribe(self, topic: str, handler, options: Optional[dict] = None) -> Optional[Any]:
|
|
189
|
+
"""Subscribes to a topic on the IronFlock Platform Message Router
|
|
190
190
|
|
|
191
191
|
Args:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
kwargs (dict): The keyword arguments to pass to the procedure.
|
|
192
|
+
topic (str): The URI of the topic to subscribe to, e.g. "com.myapp.mytopic1"
|
|
193
|
+
handler: The function to call when a message is received
|
|
194
|
+
options (dict, optional): Subscription options
|
|
196
195
|
|
|
197
196
|
Returns:
|
|
198
|
-
|
|
197
|
+
Optional[Any]: Object representing a subscription
|
|
198
|
+
"""
|
|
199
|
+
if not self.is_connected:
|
|
200
|
+
print("cannot subscribe, not connected")
|
|
201
|
+
return None
|
|
202
|
+
|
|
203
|
+
# Convert options dict to SubscribeOptions if provided
|
|
204
|
+
subscribe_options = SubscribeOptions(**options) if options else None
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
sub = await self._connection.subscribe(topic, handler, options=subscribe_options)
|
|
208
|
+
return sub
|
|
209
|
+
except Exception as e:
|
|
210
|
+
print(f"Subscribe failed: {e}")
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
async def call(self, device_key: str, topic: str, args: list = None, kwargs: dict = None, options: Optional[dict] = None):
|
|
214
|
+
"""Calls a remote procedure registered by another IronFlock device
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
device_key (str): The device key of the target device
|
|
218
|
+
topic (str): The URI of the topic to call, e.g. "com.myapp.myprocedure1"
|
|
219
|
+
args (list, optional): Positional arguments for the call. Defaults to None.
|
|
220
|
+
kwargs (dict, optional): Keyword arguments for the call. Defaults to None.
|
|
221
|
+
options (dict, optional): Call options. Defaults to None.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Any: The result of the remote procedure call
|
|
199
225
|
"""
|
|
200
226
|
if not self.is_connected:
|
|
201
227
|
print("cannot call, not connected")
|
|
202
228
|
return None
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
229
|
+
|
|
230
|
+
args = args or []
|
|
231
|
+
kwargs = kwargs or {}
|
|
232
|
+
|
|
233
|
+
# Convert options dict to CallOptions if provided
|
|
234
|
+
call_options = CallOptions(**options) if options else None
|
|
235
|
+
|
|
236
|
+
call_topic = f"{device_key}.{topic}"
|
|
237
|
+
|
|
210
238
|
try:
|
|
211
|
-
result = await self._connection.call(
|
|
212
|
-
full_topic,
|
|
213
|
-
args=args or [],
|
|
214
|
-
kwargs=kwargs or {}
|
|
215
|
-
)
|
|
239
|
+
result = await self._connection.call(call_topic, args=args, kwargs=kwargs, options=call_options)
|
|
216
240
|
return result
|
|
217
241
|
except Exception as e:
|
|
218
242
|
print(f"Call failed: {e}")
|
|
@@ -275,7 +299,8 @@ class IronFlock:
|
|
|
275
299
|
pass
|
|
276
300
|
self._main_task = None
|
|
277
301
|
|
|
278
|
-
|
|
302
|
+
if self._connection:
|
|
303
|
+
await self._connection.stop()
|
|
279
304
|
|
|
280
305
|
async def run(self):
|
|
281
306
|
"""Start the connection and keep it running"""
|
|
@@ -291,6 +316,9 @@ class IronFlock:
|
|
|
291
316
|
await asyncio.sleep(1)
|
|
292
317
|
except KeyboardInterrupt:
|
|
293
318
|
print("Shutting down...")
|
|
319
|
+
except Exception as e:
|
|
320
|
+
print(f"Exception in run(): {e}")
|
|
321
|
+
raise
|
|
294
322
|
finally:
|
|
295
323
|
await self.stop()
|
|
296
324
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|