ironflock 0.1.1__py3-none-any.whl → 1.0.5__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.
@@ -9,8 +9,18 @@ try:
9
9
  except:
10
10
  raise Exception("Environment variable SWARM_KEY not set!")
11
11
 
12
- CB_REALM = "userapps"
13
- # CB_REALM = f"swarm{SWARM_KEY}"
12
+ try:
13
+ APP_KEY = os.environ["APP_KEY"]
14
+ except:
15
+ raise Exception("Environment variable APP_KEY not set!")
16
+
17
+ try:
18
+ ENV = os.environ["ENV"].lower()
19
+ except:
20
+ raise Exception("Environment variable ENV not set!")
21
+
22
+ # CB_REALM = "userapps"
23
+ CB_REALM = f"realm-{SWARM_KEY}-{APP_KEY}-{ENV}"
14
24
 
15
25
  DATAPODS_WS_URI = "wss://cbw.datapods.io/ws-ua-usr"
16
26
  STUDIO_WS_URI_OLD = "wss://cbw.record-evolution.com/ws-ua-usr"
@@ -69,7 +79,7 @@ class AppSession(ApplicationSession):
69
79
  def create_application_session(
70
80
  serial_number: str = None,
71
81
  ) -> Tuple[ApplicationSession, ApplicationRunner]:
72
- """Creates an Autobahn ApplicationSession and ApplicationRunner, which connects to the RE Platform
82
+ """Creates an Autobahn ApplicationSession and ApplicationRunner, which connects to the IronFlock Platform
73
83
 
74
84
  Args:
75
85
  serial_number (str, optional): serial_number of device.
@@ -91,7 +101,7 @@ def create_application_session(
91
101
 
92
102
 
93
103
  def create_application_component(serial_number: str = None) -> Component:
94
- """Creates an Autobahn Component, which connects to the RE Platform
104
+ """Creates an Autobahn Component, which connects to the IronFlock Platform
95
105
 
96
106
  Args:
97
107
  serial_number (str, optional): serial_number of device.
ironflock/__init__.py CHANGED
@@ -7,4 +7,4 @@ from ironflock.ironflock import IronFlock
7
7
 
8
8
  __all__ = ["IronFlock", "create_application_component", "create_application_session"]
9
9
 
10
- __version__ = "0.0.19"
10
+ __version__ = "1.0.5"
ironflock/ironflock.py CHANGED
@@ -1,30 +1,29 @@
1
1
  import os
2
+ import asyncio
2
3
  from typing import Optional
3
4
  from autobahn.asyncio.component import Component, run
4
5
  from autobahn.wamp.interfaces import ISession
5
- from autobahn.wamp.types import PublishOptions
6
+ from autobahn.wamp.types import PublishOptions, RegisterOptions
6
7
  from autobahn.wamp.request import Publication
7
8
 
8
9
  from ironflock.AutobahnConnection import getSerialNumber, create_application_component
9
10
 
10
11
 
11
12
  class IronFlock:
12
- """Convenience class for easy to use message publishing to the RE platform.
13
+ """Conveniance class for easy-to-use message publishing in the IronFlock platform.
13
14
 
14
15
  Example:
15
16
 
16
- rw = IronFlock()
17
-
18
17
  async def main():
19
18
  while True:
20
- publication = await rw.publish("test.publish.pw", 1, "two", 3, foo="bar")
19
+ publication = await ironFlock.publish("test.publish.pw", 1, "two", 3, foo="bar")
21
20
  print(publication)
22
21
  await asyncio.sleep(3)
23
22
 
24
23
 
25
24
  if __name__ == "__main__":
26
- asyncio.get_event_loop().create_task(main())
27
- rw.run()
25
+ ironflock = IronFlock(mainFunc=main)
26
+ ironFlock.run()
28
27
  """
29
28
 
30
29
  def __init__(self, serial_number: str = None, mainFunc=None) -> None:
@@ -36,6 +35,7 @@ class IronFlock:
36
35
  """
37
36
  self._serial_number = getSerialNumber(serial_number)
38
37
  self._device_name = os.environ.get("DEVICE_NAME")
38
+ self._device_key = os.environ.get("DEVICE_KEY")
39
39
  self._component = create_application_component(serial_number)
40
40
  self._session: ISession = None
41
41
  self.mainFunc = mainFunc
@@ -44,17 +44,22 @@ class IronFlock:
44
44
  async def onJoin(session, details):
45
45
  print("component joined")
46
46
  self._session = session
47
+ self._main_task = asyncio.create_task(mainFunc())
48
+
47
49
  if self.mainFunc:
48
50
  await self.mainFunc()
49
51
 
50
52
  @self._component.on_disconnect
51
- def onDisconnect(*args, **kwargs):
52
- print("component disconnected")
53
- self._session = None
54
-
55
53
  @self._component.on_leave
56
- def onLeave(*args, **kwargs):
54
+ async def onLeave(*args, **kwargs):
57
55
  print("component left")
56
+ if self._main_task:
57
+ self._main_task.cancel()
58
+ try:
59
+ await self._main_task
60
+ except asyncio.CancelledError:
61
+ pass
62
+ self._main_task = None
58
63
  self._session = None
59
64
 
60
65
  @property
@@ -76,7 +81,7 @@ class IronFlock:
76
81
  return self._session
77
82
 
78
83
  async def publish(self, topic: str, *args, **kwargs) -> Optional[Publication]:
79
- """Publishes to the RE Platform Message Router
84
+ """Publishes to the IronFlock Platform Message Router
80
85
 
81
86
  Args:
82
87
  topic (str): The URI of the topic to publish to, e.g. "com.myapp.mytopic1"
@@ -88,6 +93,7 @@ class IronFlock:
88
93
 
89
94
  extra = {
90
95
  "DEVICE_SERIAL_NUMBER": self._serial_number,
96
+ "DEVICE_KEY": self._device_key,
91
97
  "DEVICE_NAME": self._device_name,
92
98
  "options": PublishOptions(acknowledge=True),
93
99
  }
@@ -102,6 +108,8 @@ class IronFlock:
102
108
  """Update the location of the device registered in the platform
103
109
  This will update the device's location in the master data of the platform.
104
110
  The maps in the device or group overviews will reflect the new device location in realtime.
111
+ The location history will not be stored in the platform.
112
+ If you need location history, then create a dedicated table for it.
105
113
  """
106
114
 
107
115
  payload = {
@@ -111,18 +119,43 @@ class IronFlock:
111
119
 
112
120
  extra = {
113
121
  "DEVICE_SERIAL_NUMBER": self._serial_number,
122
+ "DEVICE_KEY": self._device_key,
114
123
  "DEVICE_NAME": self._device_name
115
124
  }
116
125
 
117
126
  if hasattr(self, "_session") and hasattr(self._session, "call"):
118
127
  res = await self._session.call('ironflock.location_service.update', payload, **extra)
119
128
  return res
129
+
130
+ async def register_function(self, topic: str, func):
131
+ """Registers a function to be called when a message is received on the given topic.
132
+
133
+ Args:
134
+ topic (str): The URI of the topic to register the function for, e.g. "example.mytopic1".
135
+ func (callable): The function to call when a message is received on the topic.
136
+ """
137
+ swarm_key = os.environ.get("SWARM_KEY")
138
+ app_key = os.environ.get("APP_KEY")
139
+ env_value = os.environ.get("ENV")
140
+
141
+ topic = f"{swarm_key}.{self._device_key}.{app_key}.{env_value}.{topic}"
142
+
143
+ if self._session is not None:
144
+ await self._session.register(topic, func, options=RegisterOptions(force_reregister=True))
145
+ else:
146
+ print("cannot register function, not connected")
120
147
 
121
148
  async def publish_to_table(
122
149
  self, tablename: str, *args, **kwargs
123
150
  ) -> Optional[Publication]:
124
- """Publishes Data to a Table in the RE Platform
125
-
151
+ """Publishes Data to a Table in the IronFlock Platform. This is a conveniance function.
152
+ You can achieve the same results by simply publishing a payload to the topic
153
+
154
+ [SWARM_KEY].[APP_KEY].[your_table_name]
155
+
156
+ The SWARM_KEY and APP_KEY are provided as environment variables to the device container.
157
+ The also provided ENV variable holds either PROD or DEV to decide which topic to use, above.
158
+ This function automatically detects the environment and publishes to the correct table.
126
159
  Args:
127
160
  tablename (str): The table name of the table to publish to, e.g. "sensordata"
128
161
 
@@ -144,16 +177,7 @@ class IronFlock:
144
177
  if app_key is None:
145
178
  raise Exception("Environment variable APP_KEY not set!")
146
179
 
147
- if env_value is None:
148
- raise Exception("Environment variable ENV not set!")
149
-
150
- if not env_value in ["DEV", "PROD"]:
151
- raise Exception("Environment variable ENV must be 'PROD' or 'DEV'!")
152
-
153
- if env_value == "PROD":
154
- topic = f"{swarm_key}.{app_key}.{tablename}"
155
- else:
156
- topic = f"dev.{swarm_key}.{app_key}.{tablename}"
180
+ topic = f"{swarm_key}.{app_key}.{tablename}"
157
181
 
158
182
  pub = await self.publish(topic, *args, **kwargs)
159
183
  return pub
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: ironflock
3
+ Version: 1.0.5
4
+ Summary: SDK to integrate your IronFlock Industry 4 Apps with the IronFlock Data Infrastructure
5
+ Home-page: https://github.com/RecordEvolution/ironflock-py
6
+ Author: Record Evolution GmbH
7
+ Author-email: marko.petzold@record-evolution.de
8
+ License: MIT
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: autobahn[asyncio,serialization]==22.3.2
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: description
16
+ Dynamic: description-content-type
17
+ Dynamic: home-page
18
+ Dynamic: license
19
+ Dynamic: license-file
20
+ Dynamic: requires-dist
21
+ Dynamic: requires-python
22
+ Dynamic: summary
23
+
24
+ # ironflock
25
+
26
+ ## About
27
+
28
+ With this library you can publish data from your apps on your IoT edge hardware to the fleet data storage of the [IronFlock](https://studio.ironflock.com) devops platform.
29
+ When this library is used on a certain device the library automatically uses the private messaging realm (Unified Name Space)
30
+ of the device's fleet and the data is collected in the respective fleet database.
31
+
32
+ So if you use the library in your app, the data collection will always be private to the app user's fleet.
33
+
34
+ For more information on the IronFlock IoT Devops Platform for engineers and developers visit our [IronFlock](https://www.ironflock.com) home page.
35
+ ## Usage
36
+
37
+ ```python
38
+ import asyncio
39
+ from ironflock import IronFlock
40
+
41
+ # create an IronFlock instance to connect to the IronFlock platform data infrastructure.
42
+ # The IronFlock instance handles authentication when run on a device registered in IronFlock.
43
+ ironflock = IronFlock()
44
+
45
+ async def main():
46
+ while True:
47
+ # publish an event (if connection is not established the publish is skipped)
48
+ publication = await ironflock.publish("test.publish.com", {"temperature": 20})
49
+ print(publication)
50
+ await asyncio.sleep(3)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ ironflock = IronFlock(mainFunc=main)
55
+ ironflock.run()
56
+ ```
57
+
58
+ ## Options
59
+
60
+ The `IronFlock` `__init__` function can be configured with the following options:
61
+
62
+ ```ts
63
+ {
64
+ serial_number: string;
65
+ }
66
+ ```
67
+
68
+ **serial_number**: Used to set the serial_number of the device if the `DEVICE_SERIAL_NUMBER` environment variable does not exist. It can also be used if the user wishes to authenticate as another device.
69
+
70
+ ## Advanced Usage
71
+
72
+ If you need more control, e.g. acting on lifecycle events (`onJoin`, `onLeave`) take a look at
73
+ the [examples](https://github.com/RecordEvolution/ironflock-py/tree/main/examples) folder.
74
+
75
+
76
+ ## Development
77
+
78
+ Install the necessary components if you don't have them already:
79
+
80
+ ```shell
81
+ pip install --upgrade setuptools wheel twine
82
+ ```
83
+
84
+ Build and publish a new pypi package:
85
+
86
+ ```shell
87
+ make publish
88
+ ```
89
+
90
+ Check the package at https://pypi.org/project/ironflock/.
@@ -0,0 +1,8 @@
1
+ ironflock/AutobahnConnection.py,sha256=clwEsptqQFjDFn4dUGN4bQyb1cOnPmmNjetfTrRqckY,3687
2
+ ironflock/__init__.py,sha256=J5w21EeWOBHuxr98nMVMXAASa0tYnKppMluxtKL_x4U,264
3
+ ironflock/ironflock.py,sha256=7ugUzrt1yCG_hJAlUKiyMqALZzhrvokHBOgsPDpLxgU,6906
4
+ ironflock-1.0.5.dist-info/licenses/LICENSE,sha256=GpUKjPB381nmkbBIdX74vxXhsNZaNpngTOciss39Pjk,1073
5
+ ironflock-1.0.5.dist-info/METADATA,sha256=9htX7guGxMP0xAqdOg-uWuyy8riEEs37LrPvV1gygQY,2764
6
+ ironflock-1.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ ironflock-1.0.5.dist-info/top_level.txt,sha256=hmMdMPJuvnOTlFKYl1XQOn81vg1DE2LT7xrEXgyxcRA,10
8
+ ironflock-1.0.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,80 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: ironflock
3
- Version: 0.1.1
4
- Summary: Publishing data to a IronFlock Fleet Storage
5
- Home-page: https://github.com/RecordEvolution/ironflock-python
6
- Author: Record Evolution GmbH
7
- Author-email: marko.petzold@record-evolution.de
8
- License: MIT
9
- Requires-Python: >=3.6
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: autobahn[asyncio,compression,serialization] ==22.3.2
13
-
14
- # ironflock
15
-
16
- ## About
17
-
18
- With this library you can publishing data to IronFlock fleet storage. When this library is used on a certain device the library automatically uses the private messaging realm (Unified Name Space) of the device's fleet and the data is collected in the respective fleet database.
19
-
20
- So if you use the library in your app, the data collection will always be private to the app user's fleet.
21
-
22
- ## Usage
23
-
24
- ```python
25
- import asyncio
26
- from ironflock import IronFlock
27
-
28
- # create a ironflock instance, which auto connects to the IronFlock Platform
29
- # the ironflock instance handles authentication and reconnects when the connection is lost
30
- rw = IronFlock()
31
-
32
- async def main():
33
- while True:
34
- # publish an event (if connection is not established the publish is skipped)
35
- publication = await rw.publish("test.publish.com", {"temperature": 20})
36
- print(publication)
37
- await asyncio.sleep(3)
38
-
39
-
40
- if __name__ == "__main__":
41
- # run the main coroutine
42
- asyncio.get_event_loop().create_task(main())
43
- # run the ironflock component
44
- rw.run()
45
- ```
46
-
47
- ## Options
48
-
49
- The `IronFlock` `__init__` function can be configured with the following options:
50
-
51
- ```ts
52
- {
53
- serial_number: string;
54
- }
55
- ```
56
-
57
- **serial_number**: Used to set the serial_number of the device if the `DEVICE_SERIAL_NUMBER` environment variable does not exist. It can also be used if the user wishes to authenticate as another device.
58
-
59
- ## Advanced Usage
60
-
61
- If you need more control, e.g. acting on lifecycle events (`onJoin`, `onLeave`) take a look at
62
- the [examples](./examples/) folder.
63
-
64
-
65
- ## Development
66
-
67
- Install the necessary components if you don't have them already:
68
-
69
- ```shell
70
- pip install --upgrade setuptools wheel twine
71
- ```
72
-
73
- Build and publish a new pypi package:
74
-
75
- ```shell
76
- python setup.py sdist bdist_wheel
77
- twine upload dist/*
78
- ```
79
-
80
- Check the package at https://pypi.org/project/ironflock/.
@@ -1,8 +0,0 @@
1
- ironflock/AutobahnConnection.py,sha256=IX5VjUhRGq4-zo8cx2CH964pmoPH29sWc0eQAAG60gM,3438
2
- ironflock/__init__.py,sha256=LsyyAenv7GrvQSmPc3QJDu7_VsK7BDIvbwGC8ebEI9A,265
3
- ironflock/ironflock.py,sha256=I0T3NvY8kL7TzdjPdn7HfOxMDxsTF2qRhnklRU09dZ4,5385
4
- ironflock-0.1.1.dist-info/LICENSE,sha256=GpUKjPB381nmkbBIdX74vxXhsNZaNpngTOciss39Pjk,1073
5
- ironflock-0.1.1.dist-info/METADATA,sha256=HRePXC8dtOLvc-5tkJ347ZJEpTO0__K1pFJp_PsdzaA,2295
6
- ironflock-0.1.1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
7
- ironflock-0.1.1.dist-info/top_level.txt,sha256=hmMdMPJuvnOTlFKYl1XQOn81vg1DE2LT7xrEXgyxcRA,10
8
- ironflock-0.1.1.dist-info/RECORD,,