1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
"""
plugins/example/plugin.py
Skeleton plugin — shows every integration point.
Copy this directory, rename it, update manifest.json, and fill in your logic.
"""
from __future__ import annotations
from typing import Any, Dict, List, Optional, Type
from PyQt6.QtWidgets import QLabel, QWidget
# LabDAQ imports available at runtime
from plugins.base_plugin import LabPlugin, PluginAction, PluginContext
class ExamplePlugin(LabPlugin):
# ── Metadata ──────────────────────────────────────────────────────────
@property
def plugin_id(self) -> str:
return "example"
@property
def name(self) -> str:
return "Example Plugin"
@property
def version(self) -> str:
return "1.0.0"
@property
def description(self) -> str:
return "Skeleton showing all plugin integration points."
@property
def author(self) -> str:
return "Your Name"
# ── Lifecycle ─────────────────────────────────────────────────────────
def on_load(self, context: PluginContext) -> None:
self._ctx = context
# e.g. start a background thread, open a camera, etc.
def on_unload(self) -> None:
# Release resources — called when user disables plugin
pass
# ── Toolbar ───────────────────────────────────────────────────────────
def get_toolbar_actions(self) -> List[PluginAction]:
return [
PluginAction(
label = "Example",
icon = "🔌",
tooltip = "Open example plugin window",
checkable = True,
callback = self._on_toolbar_click,
)
]
def _on_toolbar_click(self, checked: bool):
# Open / close your plugin window here
pass
# ── Devices ───────────────────────────────────────────────────────────
def get_devices(self) -> list:
# Return BaseDevice instances — they are auto-added to the registry
# and AcquisitionEngine so their channels appear as normal signals.
#
# Example (uncomment and adapt):
# from devices.analog_input import AnalogInputDevice
# return [AnalogInputDevice("my_plugin_ai", num_channels=2, simulate=True)]
return []
# ── Custom filters ────────────────────────────────────────────────────
def get_filter_classes(self) -> Dict[str, Type]:
# Return {type_name: FilterBase subclass} for custom pipeline filters.
#
# Example:
# from .my_filter import MyFilter
# return {"my_filter": MyFilter}
return {}
# ── Settings widget ───────────────────────────────────────────────────
def get_settings_widget(self) -> Optional[QWidget]:
# Return a QWidget shown in Settings > Plugins when this plugin is enabled.
lbl = QLabel("No settings for this plugin.")
lbl.setObjectName("traceSource")
return lbl
# ── Profile persistence ───────────────────────────────────────────────
def get_save_state(self) -> Dict[str, Any]:
# Return JSON-serialisable dict saved with .labdaq profiles.
return {}
def apply_save_state(self, state: Dict[str, Any]) -> None:
# Restore plugin state when a profile is loaded.
pass
|