opensignalbox-interface 0.1.0__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.
Files changed (209) hide show
  1. opensignalbox/interface/__init__.py +42 -0
  2. opensignalbox/interface/adapters/__init__.py +3 -0
  3. opensignalbox/interface/adapters/base.py +148 -0
  4. opensignalbox/interface/adapters/controller.py +286 -0
  5. opensignalbox/interface/adapters/modbus/__init__.py +3 -0
  6. opensignalbox/interface/adapters/modbus/adapter.py +485 -0
  7. opensignalbox/interface/assets/favicon.ico +0 -0
  8. opensignalbox/interface/interfaces/__init__.py +3 -0
  9. opensignalbox/interface/interfaces/base.py +170 -0
  10. opensignalbox/interface/interfaces/basicio/__init__.py +3 -0
  11. opensignalbox/interface/interfaces/basicio/connections.py +239 -0
  12. opensignalbox/interface/interfaces/basicio/handler.py +1096 -0
  13. opensignalbox/interface/interfaces/basicio/models.py +165 -0
  14. opensignalbox/interface/interfaces/bell/__init__.py +3 -0
  15. opensignalbox/interface/interfaces/bell/connections.py +279 -0
  16. opensignalbox/interface/interfaces/bell/handler.py +802 -0
  17. opensignalbox/interface/interfaces/bell/models.py +103 -0
  18. opensignalbox/interface/interfaces/controller.py +467 -0
  19. opensignalbox/interface/main.py +187 -0
  20. opensignalbox/interface/models.py +155 -0
  21. opensignalbox/interface/routes/__init__.py +4 -0
  22. opensignalbox/interface/routes/adapters.py +119 -0
  23. opensignalbox/interface/routes/interfaces.py +104 -0
  24. opensignalbox/interface/routes.py +204 -0
  25. opensignalbox/interface/utils.py +29 -0
  26. opensignalbox/interface/version.py +5 -0
  27. opensignalbox/interface/web_ui/.gitignore +24 -0
  28. opensignalbox/interface/web_ui/README.md +5 -0
  29. opensignalbox/interface/web_ui/WEB_UI_REFACTORING.md +136 -0
  30. opensignalbox/interface/web_ui/components.json +17 -0
  31. opensignalbox/interface/web_ui/dist/assets/index-DhsEc6uo.css +2020 -0
  32. opensignalbox/interface/web_ui/dist/assets/index-t__5JZjf.js +39056 -0
  33. opensignalbox/interface/web_ui/dist/assets/index-t__5JZjf.js.map +1 -0
  34. opensignalbox/interface/web_ui/dist/index.html +14 -0
  35. opensignalbox/interface/web_ui/index.html +13 -0
  36. opensignalbox/interface/web_ui/package-lock.json +3710 -0
  37. opensignalbox/interface/web_ui/package.json +39 -0
  38. opensignalbox/interface/web_ui/src/App.vue +32 -0
  39. opensignalbox/interface/web_ui/src/assets/favicon.ico +0 -0
  40. opensignalbox/interface/web_ui/src/assets/index.css +83 -0
  41. opensignalbox/interface/web_ui/src/components/SharedVariablePicker.vue +112 -0
  42. opensignalbox/interface/web_ui/src/components/adapters/AdapterList.vue +183 -0
  43. opensignalbox/interface/web_ui/src/components/adapters/types.ts +35 -0
  44. opensignalbox/interface/web_ui/src/components/interfaces/InterfaceList.vue +200 -0
  45. opensignalbox/interface/web_ui/src/components/ui/badge/Badge.vue +16 -0
  46. opensignalbox/interface/web_ui/src/components/ui/badge/index.ts +25 -0
  47. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/Breadcrumb.vue +13 -0
  48. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +22 -0
  49. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbItem.vue +16 -0
  50. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbLink.vue +19 -0
  51. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbList.vue +16 -0
  52. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbPage.vue +19 -0
  53. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +21 -0
  54. opensignalbox/interface/web_ui/src/components/ui/breadcrumb/index.ts +7 -0
  55. opensignalbox/interface/web_ui/src/components/ui/button/Button.vue +26 -0
  56. opensignalbox/interface/web_ui/src/components/ui/button/index.ts +35 -0
  57. opensignalbox/interface/web_ui/src/components/ui/card/Card.vue +21 -0
  58. opensignalbox/interface/web_ui/src/components/ui/card/CardContent.vue +14 -0
  59. opensignalbox/interface/web_ui/src/components/ui/card/CardDescription.vue +14 -0
  60. opensignalbox/interface/web_ui/src/components/ui/card/CardFooter.vue +14 -0
  61. opensignalbox/interface/web_ui/src/components/ui/card/CardHeader.vue +14 -0
  62. opensignalbox/interface/web_ui/src/components/ui/card/CardTitle.vue +18 -0
  63. opensignalbox/interface/web_ui/src/components/ui/card/index.ts +6 -0
  64. opensignalbox/interface/web_ui/src/components/ui/checkbox/Checkbox.vue +33 -0
  65. opensignalbox/interface/web_ui/src/components/ui/checkbox/index.ts +1 -0
  66. opensignalbox/interface/web_ui/src/components/ui/collapsible/Collapsible.vue +15 -0
  67. opensignalbox/interface/web_ui/src/components/ui/collapsible/CollapsibleContent.vue +11 -0
  68. opensignalbox/interface/web_ui/src/components/ui/collapsible/CollapsibleTrigger.vue +11 -0
  69. opensignalbox/interface/web_ui/src/components/ui/collapsible/index.ts +3 -0
  70. opensignalbox/interface/web_ui/src/components/ui/command/Command.vue +30 -0
  71. opensignalbox/interface/web_ui/src/components/ui/command/CommandDialog.vue +21 -0
  72. opensignalbox/interface/web_ui/src/components/ui/command/CommandEmpty.vue +20 -0
  73. opensignalbox/interface/web_ui/src/components/ui/command/CommandGroup.vue +29 -0
  74. opensignalbox/interface/web_ui/src/components/ui/command/CommandInput.vue +33 -0
  75. opensignalbox/interface/web_ui/src/components/ui/command/CommandItem.vue +26 -0
  76. opensignalbox/interface/web_ui/src/components/ui/command/CommandList.vue +27 -0
  77. opensignalbox/interface/web_ui/src/components/ui/command/CommandSeparator.vue +23 -0
  78. opensignalbox/interface/web_ui/src/components/ui/command/CommandShortcut.vue +14 -0
  79. opensignalbox/interface/web_ui/src/components/ui/command/index.ts +9 -0
  80. opensignalbox/interface/web_ui/src/components/ui/dialog/Dialog.vue +14 -0
  81. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogClose.vue +11 -0
  82. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogContent.vue +50 -0
  83. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogDescription.vue +24 -0
  84. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogFooter.vue +19 -0
  85. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogHeader.vue +16 -0
  86. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  87. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogTitle.vue +29 -0
  88. opensignalbox/interface/web_ui/src/components/ui/dialog/DialogTrigger.vue +11 -0
  89. opensignalbox/interface/web_ui/src/components/ui/dialog/index.ts +9 -0
  90. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
  91. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  92. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuContent.vue +38 -0
  93. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
  94. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
  95. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
  96. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
  97. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
  98. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
  99. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  100. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  101. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  102. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
  103. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
  104. opensignalbox/interface/web_ui/src/components/ui/dropdown-menu/index.ts +16 -0
  105. opensignalbox/interface/web_ui/src/components/ui/form/FormControl.vue +16 -0
  106. opensignalbox/interface/web_ui/src/components/ui/form/FormDescription.vue +20 -0
  107. opensignalbox/interface/web_ui/src/components/ui/form/FormItem.vue +19 -0
  108. opensignalbox/interface/web_ui/src/components/ui/form/FormLabel.vue +23 -0
  109. opensignalbox/interface/web_ui/src/components/ui/form/FormMessage.vue +16 -0
  110. opensignalbox/interface/web_ui/src/components/ui/form/index.ts +7 -0
  111. opensignalbox/interface/web_ui/src/components/ui/form/injectionKeys.ts +4 -0
  112. opensignalbox/interface/web_ui/src/components/ui/form/useFormField.ts +30 -0
  113. opensignalbox/interface/web_ui/src/components/ui/input/Input.vue +24 -0
  114. opensignalbox/interface/web_ui/src/components/ui/input/index.ts +1 -0
  115. opensignalbox/interface/web_ui/src/components/ui/label/Label.vue +27 -0
  116. opensignalbox/interface/web_ui/src/components/ui/label/index.ts +1 -0
  117. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberField.vue +23 -0
  118. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldContent.vue +14 -0
  119. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldDecrement.vue +25 -0
  120. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldIncrement.vue +25 -0
  121. opensignalbox/interface/web_ui/src/components/ui/number-field/NumberFieldInput.vue +16 -0
  122. opensignalbox/interface/web_ui/src/components/ui/number-field/index.ts +5 -0
  123. opensignalbox/interface/web_ui/src/components/ui/popover/Popover.vue +15 -0
  124. opensignalbox/interface/web_ui/src/components/ui/popover/PopoverContent.vue +48 -0
  125. opensignalbox/interface/web_ui/src/components/ui/popover/PopoverTrigger.vue +11 -0
  126. opensignalbox/interface/web_ui/src/components/ui/popover/index.ts +3 -0
  127. opensignalbox/interface/web_ui/src/components/ui/radio-group/RadioGroup.vue +25 -0
  128. opensignalbox/interface/web_ui/src/components/ui/radio-group/RadioGroupItem.vue +39 -0
  129. opensignalbox/interface/web_ui/src/components/ui/radio-group/index.ts +2 -0
  130. opensignalbox/interface/web_ui/src/components/ui/scroll-area/ScrollArea.vue +29 -0
  131. opensignalbox/interface/web_ui/src/components/ui/scroll-area/ScrollBar.vue +30 -0
  132. opensignalbox/interface/web_ui/src/components/ui/scroll-area/index.ts +2 -0
  133. opensignalbox/interface/web_ui/src/components/ui/select/Select.vue +15 -0
  134. opensignalbox/interface/web_ui/src/components/ui/select/SelectContent.vue +53 -0
  135. opensignalbox/interface/web_ui/src/components/ui/select/SelectGroup.vue +19 -0
  136. opensignalbox/interface/web_ui/src/components/ui/select/SelectItem.vue +44 -0
  137. opensignalbox/interface/web_ui/src/components/ui/select/SelectItemText.vue +11 -0
  138. opensignalbox/interface/web_ui/src/components/ui/select/SelectLabel.vue +13 -0
  139. opensignalbox/interface/web_ui/src/components/ui/select/SelectScrollDownButton.vue +24 -0
  140. opensignalbox/interface/web_ui/src/components/ui/select/SelectScrollUpButton.vue +24 -0
  141. opensignalbox/interface/web_ui/src/components/ui/select/SelectSeparator.vue +17 -0
  142. opensignalbox/interface/web_ui/src/components/ui/select/SelectTrigger.vue +31 -0
  143. opensignalbox/interface/web_ui/src/components/ui/select/SelectValue.vue +11 -0
  144. opensignalbox/interface/web_ui/src/components/ui/select/index.ts +11 -0
  145. opensignalbox/interface/web_ui/src/components/ui/separator/Separator.vue +35 -0
  146. opensignalbox/interface/web_ui/src/components/ui/separator/index.ts +1 -0
  147. opensignalbox/interface/web_ui/src/components/ui/sheet/Sheet.vue +14 -0
  148. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetClose.vue +11 -0
  149. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetContent.vue +56 -0
  150. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetDescription.vue +22 -0
  151. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetFooter.vue +19 -0
  152. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetHeader.vue +16 -0
  153. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetTitle.vue +22 -0
  154. opensignalbox/interface/web_ui/src/components/ui/sheet/SheetTrigger.vue +11 -0
  155. opensignalbox/interface/web_ui/src/components/ui/sheet/index.ts +31 -0
  156. opensignalbox/interface/web_ui/src/components/ui/table/Table.vue +16 -0
  157. opensignalbox/interface/web_ui/src/components/ui/table/TableBody.vue +14 -0
  158. opensignalbox/interface/web_ui/src/components/ui/table/TableCaption.vue +14 -0
  159. opensignalbox/interface/web_ui/src/components/ui/table/TableCell.vue +21 -0
  160. opensignalbox/interface/web_ui/src/components/ui/table/TableEmpty.vue +37 -0
  161. opensignalbox/interface/web_ui/src/components/ui/table/TableFooter.vue +14 -0
  162. opensignalbox/interface/web_ui/src/components/ui/table/TableHead.vue +14 -0
  163. opensignalbox/interface/web_ui/src/components/ui/table/TableHeader.vue +14 -0
  164. opensignalbox/interface/web_ui/src/components/ui/table/TableRow.vue +14 -0
  165. opensignalbox/interface/web_ui/src/components/ui/table/index.ts +9 -0
  166. opensignalbox/interface/web_ui/src/components/ui/tabs/Tabs.vue +15 -0
  167. opensignalbox/interface/web_ui/src/components/ui/tabs/TabsContent.vue +22 -0
  168. opensignalbox/interface/web_ui/src/components/ui/tabs/TabsList.vue +25 -0
  169. opensignalbox/interface/web_ui/src/components/ui/tabs/TabsTrigger.vue +29 -0
  170. opensignalbox/interface/web_ui/src/components/ui/tabs/index.ts +4 -0
  171. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInput.vue +22 -0
  172. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputInput.vue +19 -0
  173. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputItem.vue +22 -0
  174. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
  175. opensignalbox/interface/web_ui/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
  176. opensignalbox/interface/web_ui/src/components/ui/tags-input/index.ts +5 -0
  177. opensignalbox/interface/web_ui/src/components/ui/textarea/Textarea.vue +24 -0
  178. opensignalbox/interface/web_ui/src/components/ui/textarea/index.ts +1 -0
  179. opensignalbox/interface/web_ui/src/components/ui/tooltip/Tooltip.vue +14 -0
  180. opensignalbox/interface/web_ui/src/components/ui/tooltip/TooltipContent.vue +31 -0
  181. opensignalbox/interface/web_ui/src/components/ui/tooltip/TooltipProvider.vue +11 -0
  182. opensignalbox/interface/web_ui/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
  183. opensignalbox/interface/web_ui/src/components/ui/tooltip/index.ts +4 -0
  184. opensignalbox/interface/web_ui/src/libs/utils.ts +6 -0
  185. opensignalbox/interface/web_ui/src/main.ts +141 -0
  186. opensignalbox/interface/web_ui/src/views/Overview.vue +11 -0
  187. opensignalbox/interface/web_ui/src/views/Settings.vue +6 -0
  188. opensignalbox/interface/web_ui/src/views/SleafordEast.vue +205 -0
  189. opensignalbox/interface/web_ui/src/views/adapters/modbus/ModbusAdapterEdit.vue +343 -0
  190. opensignalbox/interface/web_ui/src/views/adapters/modbus/ModbusAdapterView.vue +270 -0
  191. opensignalbox/interface/web_ui/src/views/interfaces/InterfaceCreate.vue +0 -0
  192. opensignalbox/interface/web_ui/src/views/interfaces/basicio/BasicIOInterfaceEdit.vue +795 -0
  193. opensignalbox/interface/web_ui/src/views/interfaces/basicio/BasicIOInterfaceView.vue +648 -0
  194. opensignalbox/interface/web_ui/src/views/interfaces/bell/BellInterfaceEdit.vue +790 -0
  195. opensignalbox/interface/web_ui/src/views/interfaces/bell/BellInterfaceView.vue +437 -0
  196. opensignalbox/interface/web_ui/src/vite-env.d.ts +1 -0
  197. opensignalbox/interface/web_ui/tailwind.config.js +94 -0
  198. opensignalbox/interface/web_ui/tsconfig.app.json +27 -0
  199. opensignalbox/interface/web_ui/tsconfig.json +30 -0
  200. opensignalbox/interface/web_ui/tsconfig.node.json +12 -0
  201. opensignalbox/interface/web_ui/tsconfig.tsbuildinfo +1 -0
  202. opensignalbox/interface/web_ui/vite.config.d.ts +2 -0
  203. opensignalbox/interface/web_ui/vite.config.js +60 -0
  204. opensignalbox/interface/web_ui/vite.config.ts +62 -0
  205. opensignalbox_interface-0.1.0.dist-info/METADATA +49 -0
  206. opensignalbox_interface-0.1.0.dist-info/RECORD +209 -0
  207. opensignalbox_interface-0.1.0.dist-info/WHEEL +4 -0
  208. opensignalbox_interface-0.1.0.dist-info/entry_points.txt +2 -0
  209. opensignalbox_interface-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,239 @@
1
+ import logging
2
+ from abc import ABC, abstractmethod
3
+ from math import ceil
4
+
5
+ from opensignalbox.interface.adapters.base import BaseAdapter
6
+ from opensignalbox.interface.interfaces.basicio.models import BasicIOInterface
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class BasicIOConnection(ABC):
12
+ """Base abstract class for all basic I/O connections."""
13
+
14
+ @classmethod
15
+ @abstractmethod
16
+ def connect(
17
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
18
+ ) -> bool:
19
+ """Connect to the basic I/O interface."""
20
+ pass
21
+
22
+ @classmethod
23
+ @abstractmethod
24
+ def disconnect(
25
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
26
+ ) -> bool:
27
+ """Disconnect from the basic I/O interface."""
28
+ pass
29
+
30
+ @classmethod
31
+ @abstractmethod
32
+ def send_data(
33
+ cls,
34
+ interface: BasicIOInterface,
35
+ data: bytearray,
36
+ adapter: BaseAdapter | None = None,
37
+ ) -> None:
38
+ """Send data through the basic I/O interface."""
39
+ pass
40
+
41
+ @classmethod
42
+ @abstractmethod
43
+ def receive_data(
44
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
45
+ ) -> bytearray:
46
+ """Receive data from the basic I/O interface."""
47
+ pass
48
+
49
+
50
+ class BasicIOTestConnection(BasicIOConnection):
51
+ """Test implementation of the BasicIOConnection for unit testing."""
52
+
53
+ @classmethod
54
+ def connect(
55
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
56
+ ) -> bool:
57
+ """Simulate connecting to the interface."""
58
+ logger.debug(
59
+ f"Connecting to interface {interface.system_name} with test connection."
60
+ )
61
+ interface.is_connected = True
62
+ return True
63
+
64
+ @classmethod
65
+ def disconnect(
66
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
67
+ ) -> bool:
68
+ """Simulate disconnecting from the interface."""
69
+ logger.debug(
70
+ f"Disconnecting from interface {interface.system_name} with test connection."
71
+ )
72
+ interface.is_connected = False
73
+ return True
74
+
75
+ @classmethod
76
+ def send_data(
77
+ cls,
78
+ interface: BasicIOInterface,
79
+ data: bytearray,
80
+ adapter: BaseAdapter | None = None,
81
+ ) -> None:
82
+ """Simulate sending data."""
83
+ logger.debug(
84
+ f"Sending data to interface {interface.system_name} with test connection."
85
+ )
86
+ return
87
+
88
+ @classmethod
89
+ def receive_data(
90
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
91
+ ) -> bytearray:
92
+ """Simulate receiving data."""
93
+ logger.debug(
94
+ f"Receiving data from interface {interface.system_name} with test connection."
95
+ )
96
+ # Simulate receiving data
97
+ return bytearray(b"Test Data")
98
+
99
+
100
+ class BasicIOModbusConnection(BasicIOConnection):
101
+ """Modbus implementation of the BasicIOConnection."""
102
+
103
+ @classmethod
104
+ def connect(
105
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
106
+ ) -> bool:
107
+ """Connect to the Modbus interface."""
108
+ logger.debug(f"Connecting to BasicIO Modbus interface {interface.system_name}.")
109
+ if adapter is not None:
110
+ if not adapter.is_connected:
111
+ adapter.connect()
112
+ if adapter.is_connected:
113
+ interface.is_connected = True
114
+ return True
115
+ else:
116
+ interface.is_connected = True
117
+ return True
118
+ return False
119
+
120
+ @classmethod
121
+ def disconnect(
122
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
123
+ ) -> bool:
124
+ """Disconnect from the Modbus interface."""
125
+ logger.debug(
126
+ f"Disconnecting from BasicIO Modbus interface {interface.system_name}."
127
+ )
128
+ interface.is_connected = False
129
+ return True
130
+
131
+ @classmethod
132
+ def send_data(
133
+ cls,
134
+ interface: BasicIOInterface,
135
+ data: bytearray,
136
+ adapter: BaseAdapter | None = None,
137
+ ) -> None:
138
+ """Send data through the Modbus interface."""
139
+ if adapter is not None and interface.modbus_address is not None:
140
+ command = 15
141
+ cmd = interface.modbus_address.to_bytes()
142
+ cmd += command.to_bytes()
143
+ cmd += interface.output_start_address.to_bytes(2)
144
+ cmd += (interface.output_bits).to_bytes(2)
145
+ cmd += len(data).to_bytes()
146
+ cmd += data
147
+ adapter.attempt_write(cmd)
148
+ adapter.attempt_read()
149
+ return
150
+
151
+ @classmethod
152
+ def receive_data(
153
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
154
+ ) -> bytearray:
155
+ """Receive data from the Modbus interface."""
156
+ if adapter is not None and interface.modbus_address is not None:
157
+ command = 3
158
+ cmd = interface.modbus_address.to_bytes()
159
+ cmd += command.to_bytes()
160
+ cmd += interface.input_start_address.to_bytes(2)
161
+ cmd += ceil(interface.input_bits / 16).to_bytes(2)
162
+ adapter.attempt_write(cmd)
163
+ return adapter.attempt_read()
164
+ return bytearray(b"")
165
+
166
+
167
+ class BasicIODingtianModbusConnection(BasicIOConnection):
168
+ """Modbus implementation of the BasicIOConnection for Dingtian boards."""
169
+
170
+ @classmethod
171
+ def connect(
172
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
173
+ ) -> bool:
174
+ """Connect to the Dingtian Modbus interface."""
175
+ logger.debug(
176
+ f"Connecting to BasicIO Dingtian Modbus interface {interface.system_name}."
177
+ )
178
+ if adapter is not None:
179
+ if not adapter.is_connected:
180
+ adapter.connect()
181
+ if adapter.is_connected:
182
+ interface.is_connected = True
183
+ return True
184
+ else:
185
+ interface.is_connected = True
186
+ return True
187
+ return False
188
+
189
+ @classmethod
190
+ def disconnect(
191
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
192
+ ) -> bool:
193
+ """Disconnect from the Dingtian Modbus interface."""
194
+ logger.debug(
195
+ f"Disconnecting from BasicIO Dingtian Modbus interface {interface.system_name}."
196
+ )
197
+ interface.is_connected = False
198
+ return True
199
+
200
+ @classmethod
201
+ def send_data(
202
+ cls,
203
+ interface: BasicIOInterface,
204
+ data: bytearray,
205
+ adapter: BaseAdapter | None = None,
206
+ ) -> None:
207
+ """Send data through the Dingtian Modbus interface."""
208
+ if adapter is not None and interface.modbus_address is not None:
209
+ command = 16
210
+ cmd = interface.modbus_address.to_bytes()
211
+ cmd += command.to_bytes()
212
+ cmd += interface.output_start_address.to_bytes(2)
213
+ cmd += 0x04.to_bytes(2)
214
+ cmd += 0x08.to_bytes()
215
+ cmd += 0xFFFF.to_bytes(2)
216
+ cmd += 0x00.to_bytes(2)
217
+ cmd += data
218
+ cmd += 0x00.to_bytes(2)
219
+ logger.debug(
220
+ f"Sending data to Dingtian interface {interface.system_name}. Command: {cmd.hex()}"
221
+ )
222
+ adapter.attempt_write(cmd)
223
+ adapter.attempt_read()
224
+ return
225
+
226
+ @classmethod
227
+ def receive_data(
228
+ cls, interface: BasicIOInterface, adapter: BaseAdapter | None = None
229
+ ) -> bytearray:
230
+ """Receive data from the Dingtian Modbus interface."""
231
+ if adapter is not None and interface.modbus_address is not None:
232
+ command = 3
233
+ cmd = interface.modbus_address.to_bytes()
234
+ cmd += command.to_bytes()
235
+ cmd += interface.input_start_address.to_bytes(2)
236
+ cmd += ceil(interface.input_bits / 16).to_bytes(2)
237
+ adapter.attempt_write(cmd)
238
+ return adapter.attempt_read()
239
+ return bytearray(b"")