leaf-framework 0.4.0__tar.gz → 0.5.0__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 (104) hide show
  1. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/PKG-INFO +1 -1
  2. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/file_watcher.py +3 -1
  3. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/modbus_watcher.py +26 -5
  4. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/mqtt.py +9 -3
  5. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/pyproject.toml +1 -1
  6. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/LICENSE +0 -0
  7. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/README.md +0 -0
  8. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/__init__.py +0 -0
  9. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/adapters/__init__.py +0 -0
  10. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/adapters/core_adapters/__init__.py +0 -0
  11. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/adapters/core_adapters/continuous_experiment_adapter.py +0 -0
  12. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/adapters/core_adapters/discrete_experiment_adapter.py +0 -0
  13. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/adapters/core_adapters/upload_adapter.py +0 -0
  14. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/adapters/equipment_adapter.py +0 -0
  15. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/config/configuration.yaml +0 -0
  16. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/data/marketplace.yaml +0 -0
  17. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/error_handler/__init__.py +0 -0
  18. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/error_handler/error_holder.py +0 -0
  19. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/error_handler/exceptions.py +0 -0
  20. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/measurement_handler/__init__.py +0 -0
  21. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/measurement_handler/handler.py +0 -0
  22. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/measurement_handler/measurements.yaml +0 -0
  23. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/measurement_handler/terms.py +0 -0
  24. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/.gitkeep +0 -0
  25. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/__init__.py +0 -0
  26. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/__init__.py +0 -0
  27. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/ble_watcher.py +0 -0
  28. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/db_watcher.py +0 -0
  29. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/event_watcher.py +0 -0
  30. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/external_api_watcher.py +0 -0
  31. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/external_event_watcher.py +0 -0
  32. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/http_watcher.py +0 -0
  33. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/mqtt_external_event_watcher.py +0 -0
  34. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/mqtt_watcher.py +0 -0
  35. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/opc_watcher.py +0 -0
  36. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/polling_watcher.py +0 -0
  37. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/input_modules/simple_watcher.py +0 -0
  38. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/__init__.py +0 -0
  39. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/carbon_dioxide.py +0 -0
  40. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/dissolved_oxygen.py +0 -0
  41. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/fluorescence.py +0 -0
  42. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/measurement_module.py +0 -0
  43. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/optical_density.py +0 -0
  44. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/ph.py +0 -0
  45. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/measurement_modules/temperature.py +0 -0
  46. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/__init__.py +0 -0
  47. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/file.py +0 -0
  48. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/keydb.py +0 -0
  49. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/output_module.py +0 -0
  50. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/sql.py +0 -0
  51. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/output_modules/topic_store.py +0 -0
  52. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/__init__.py +0 -0
  53. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/control.py +0 -0
  54. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/error.py +0 -0
  55. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/external_event_phase.py +0 -0
  56. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/initialisation.py +0 -0
  57. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/measure.py +0 -0
  58. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/phase.py +0 -0
  59. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/start.py +0 -0
  60. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/phase_modules/stop.py +0 -0
  61. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/process_modules/__init__.py +0 -0
  62. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/process_modules/continous_module.py +0 -0
  63. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/process_modules/discrete_module.py +0 -0
  64. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/process_modules/external_event_process.py +0 -0
  65. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/process_modules/process_module.py +0 -0
  66. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/modules/process_modules/upload_module.py +0 -0
  67. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/__init__.py +0 -0
  68. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/abstract_leaf.py +0 -0
  69. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/equipment_actions.yaml +0 -0
  70. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/equipment_data.yaml +0 -0
  71. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/metadata.py +0 -0
  72. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/py.typed +0 -0
  73. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/register/topic_utilities.py +0 -0
  74. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/registry/discovery.py +0 -0
  75. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/registry/loader.py +0 -0
  76. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/registry/registry.py +0 -0
  77. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/registry/utils.py +0 -0
  78. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/start.py +0 -0
  79. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/__init__.py +0 -0
  80. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/adapter_ui_extension.py +0 -0
  81. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/components/__init__.py +0 -0
  82. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/components/header.py +0 -0
  83. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/constants.py +0 -0
  84. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/desktop_launcher.py +0 -0
  85. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/images/icon.icns +0 -0
  86. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/images/icon.ico +0 -0
  87. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/images/icon.svg +0 -0
  88. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/interface.py +0 -0
  89. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/markdown/configuration_help.md +0 -0
  90. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/markdown/documentation_main.md +0 -0
  91. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/markdown/documentation_protips.md +0 -0
  92. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/scripts.js +0 -0
  93. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/styles.css +0 -0
  94. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/tabs/__init__.py +0 -0
  95. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/tabs/adapters.py +0 -0
  96. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/tabs/configuration.py +0 -0
  97. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/tabs/documentation.py +0 -0
  98. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/tabs/logs.py +0 -0
  99. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/tabs/monitoring.py +0 -0
  100. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/ui/utils.py +0 -0
  101. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/utility/config_utils.py +0 -0
  102. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/utility/logger/__init__.py +0 -0
  103. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/utility/logger/logger_utils.py +0 -0
  104. {leaf_framework-0.4.0 → leaf_framework-0.5.0}/leaf/utility/running_utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: leaf-framework
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Lightweight Adapter Framework (LEAF)
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -77,6 +77,7 @@ class FileWatcher(FileSystemEventHandler, EventWatcher):
77
77
  use_polling: bool = True,
78
78
  polling_interval: float = 1.0,
79
79
  skip_existing: bool = False,
80
+ recursive: bool = False,
80
81
  ) -> None:
81
82
  """
82
83
  Initialise FileWatcher.
@@ -121,6 +122,7 @@ class FileWatcher(FileSystemEventHandler, EventWatcher):
121
122
  self._use_polling = use_polling
122
123
  self._polling_interval = polling_interval
123
124
  self._skip_existing = skip_existing
125
+ self._recursive = recursive
124
126
 
125
127
  self._last_created: dict = {} # Track creation time per file path
126
128
  self._last_modified: dict = {} # Track modification time per file path
@@ -154,7 +156,7 @@ class FileWatcher(FileSystemEventHandler, EventWatcher):
154
156
  logger.debug("Using native filesystem observer")
155
157
  for path in self._paths:
156
158
  logger.debug(f"Watching path: {path}")
157
- self._observer.schedule(self, path, recursive=False)
159
+ self._observer.schedule(self, path, recursive=self._recursive)
158
160
  if not self._observer.is_alive():
159
161
  logger.debug("Starting observer thread...")
160
162
  self._observer.start()
@@ -26,9 +26,15 @@ class ModbusWatcher(ExternalEventWatcher):
26
26
 
27
27
  Each entry in `registers` may contain:
28
28
  name (str): Key used in the output payload.
29
- address (int): Modbus holding register address. Accepts either 4xxxx notation
30
- (e.g. 40301, offset subtracted automatically) or 0-based protocol
31
- address (e.g. 300).
29
+ address (int): Modbus register address. Accepts 4xxxx notation for holding
30
+ registers (e.g. 40301, offset subtracted automatically), 3xxxx
31
+ notation for input registers (e.g. 30009, offset subtracted
32
+ automatically), or a 0-based protocol address (e.g. 300).
33
+ register_type (str): "holding" (default) or "input". Only needed when `address`
34
+ is a 0-based protocol address, since that notation does not
35
+ indicate which register bank to read from. Ignored when
36
+ `address` is given in 3xxxx/4xxxx notation, which determines
37
+ the register bank automatically.
32
38
  count (int): Number of consecutive registers to read (default 1).
33
39
  scale (float): Multiply the raw value by this factor (default 1.0).
34
40
  Applied only when count == 1.
@@ -53,6 +59,9 @@ class ModbusWatcher(ExternalEventWatcher):
53
59
  - name: last_ir_ts
54
60
  address: 42002
55
61
  count: 2
62
+ - name: h2_flow_rate
63
+ address: 30009
64
+ scale: 0.1
56
65
  """
57
66
 
58
67
  def __init__(
@@ -121,8 +130,20 @@ class ModbusWatcher(ExternalEventWatcher):
121
130
  continue
122
131
 
123
132
  raw_address = int(address)
124
- protocol_address = raw_address - 40001 if raw_address >= 40001 else raw_address
125
- result = self._client.read_holding_registers(
133
+ if raw_address >= 40001:
134
+ protocol_address = raw_address - 40001
135
+ register_type = "holding"
136
+ elif raw_address >= 30001:
137
+ protocol_address = raw_address - 30001
138
+ register_type = "input"
139
+ else:
140
+ protocol_address = raw_address
141
+ register_type = reg.get("register_type", "holding")
142
+
143
+ read_fn = (
144
+ self._client.read_input_registers if register_type == "input" else self._client.read_holding_registers
145
+ )
146
+ result = read_fn(
126
147
  address=protocol_address,
127
148
  count=count,
128
149
  device_id=self._device_id,
@@ -8,7 +8,7 @@ import paho.mqtt.client as mqtt
8
8
  from paho.mqtt.enums import CallbackAPIVersion
9
9
 
10
10
  from leaf.error_handler.error_holder import ErrorHolder
11
- from leaf.error_handler.exceptions import AdapterBuildError, ClientUnreachableError, SeverityLevel
11
+ from leaf.error_handler.exceptions import AdapterBuildError, ClientUnreachableError, LEAFError, SeverityLevel
12
12
  from leaf.modules.output_modules.output_module import OutputModule
13
13
  from leaf.utility.logger.logger_utils import get_logger
14
14
 
@@ -491,8 +491,14 @@ class MQTT(OutputModule):
491
491
  "timestamp": time.time(),
492
492
  "datetime": time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime()),
493
493
  }
494
- logger.info(f"Publishing heartbeat to '{self._heartbeat_topic}': {payload}")
495
- self.transmit(self._heartbeat_topic, payload)
494
+ logger.debug(f"Publishing heartbeat to '{self._heartbeat_topic}': {payload}")
495
+ try:
496
+ self.transmit(self._heartbeat_topic, payload)
497
+ except LEAFError as e:
498
+ # Must not propagate - an unhandled exception here (e.g. the broker
499
+ # connection not being fully up yet) would silently kill this daemon
500
+ # thread and stop all future heartbeats.
501
+ logger.debug(f"Heartbeat publish failed, will retry next interval: {e}")
496
502
  if self._heartbeat_stop.wait(self._heartbeat_interval):
497
503
  break
498
504
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "leaf-framework"
3
- version = "0.4.0"
3
+ version = "0.5.0"
4
4
  description = "Lightweight Adapter Framework (LEAF)"
5
5
  authors = [
6
6
  "Matthew Crowther <nmc215@ncl.ac.uk>",
File without changes
File without changes