hid-usb-relay 25.0.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.
File without changes
File without changes
@@ -0,0 +1,116 @@
1
+ import socket
2
+ import uvicorn
3
+ import logging
4
+ from fastapi import FastAPI, HTTPException
5
+ from fastapi.responses import HTMLResponse
6
+
7
+ from hid_usb_relay.usb_relay import (
8
+ set_relay_device_state,
9
+ set_relay_device_relay_state,
10
+ get_relay_device_state,
11
+ get_relay_device_relay_state,
12
+ set_default_relay_device_state,
13
+ set_default_relay_device_relay_state,
14
+ get_default_relay_device_state,
15
+ get_default_relay_device_relay_state,
16
+ )
17
+
18
+ app = FastAPI()
19
+
20
+ logging.basicConfig(level=logging.INFO)
21
+
22
+ helper_text = """
23
+ <h1>YCR HID USB Relay Web API</h1>
24
+ <h2>Endpoints</h2>
25
+ <ul>
26
+ <li><b>/</b> ➖ This page</li>
27
+ <li><b>/relay/1/on</b> ➖ Turn ON Relay 1 of Default Relay Device</li>
28
+ <li><b>/relay/2/off</b> ➖ Turn OFF Relay 2 of Default Relay Device</li>
29
+ <li><b>/relay/all/on</b> ➖ Turn ON all Relays of Default Relay Device</li>
30
+ <li><b>/relay/all/off</b> ➖ Turn OFF all Relays of Default Relay Device</li>
31
+ <li><b>/relay/HURTM/1/on</b> ➖ Turn ON Relay 1 of Relay Id "HURTM"</li>
32
+ <li><b>/relay/HURTM/2/off</b> ➖ Turn OFF Relay 2 of Relay Id "HURTM"</li>
33
+ <li><b>/relay/HURTM/all/on</b> ➖ Turn ON all Relays of Relay Id "HURTM"</li>
34
+ <li><b>/relay/HURTM/all/off</b> ➖ Turn OFF all Relays of Relay Id "HURTM"</li>
35
+ </ul>
36
+ """
37
+
38
+ @app.get("/", response_class=HTMLResponse)
39
+ def root_page_help() -> str:
40
+ """
41
+ Provides help text for the root page.
42
+
43
+ Returns:
44
+ str: The help text for the root page.
45
+ """
46
+ return helper_text
47
+
48
+ @app.get("/relay/{relay_id}/{relay_number}/{relay_state}")
49
+ def relay_control_by_id(relay_id: str, relay_number: str, relay_state: str) -> dict:
50
+ """
51
+ Controls the state of a relay by its ID and relay number.
52
+
53
+ Args:
54
+ relay_id (str): The ID of the relay device.
55
+ relay_number (str): The number of the relay to control. Use "all" to control all relays.
56
+ relay_state (str): The desired state of the relay (e.g., "on", "off").
57
+
58
+ Returns:
59
+ dict: A dictionary containing the status of the operation and the current state of the relay.
60
+
61
+ Raises:
62
+ HTTPException: If the relay state could not be set or if an internal server error occurs.
63
+ """
64
+ try:
65
+ if relay_number.lower() == "all":
66
+ ret_val = set_relay_device_state(relay_id, relay_state.upper())
67
+ else:
68
+ ret_val = set_relay_device_relay_state(relay_id, relay_number, relay_state.upper())
69
+
70
+ if ret_val:
71
+ if relay_number.lower() == "all":
72
+ response_text = get_relay_device_state(relay_id)
73
+ else:
74
+ response_text = get_relay_device_relay_state(relay_id, relay_number)
75
+ return {"status": "success", "relay_state": response_text}
76
+ else:
77
+ raise HTTPException(status_code=400, detail="Failed to set relay state. Check command.")
78
+ except Exception as e:
79
+ logging.error(f"Error in relay_control_by_id: {e}")
80
+ raise HTTPException(status_code=500, detail="Internal Server Error")
81
+
82
+ @app.get("/relay/{relay_number}/{relay_state}")
83
+ def default_relay_control(relay_number: str, relay_state: str) -> dict:
84
+ """
85
+ Controls the state of a relay or all relays on the default relay device.
86
+
87
+ Args:
88
+ relay_number (str): The relay number to control. Use "all" to control all relays.
89
+ relay_state (str): The desired state of the relay(s). Typically "on" or "off".
90
+
91
+ Returns:
92
+ dict: A dictionary containing the status of the operation and the current state of the relay(s).
93
+
94
+ Raises:
95
+ HTTPException: If the relay state could not be set or if an internal error occurs.
96
+ """
97
+ try:
98
+ if relay_number.lower() == "all":
99
+ ret_val = set_default_relay_device_state(relay_state.upper())
100
+ else:
101
+ ret_val = set_default_relay_device_relay_state(relay_number, relay_state.upper())
102
+
103
+ if ret_val:
104
+ if relay_number.lower() == "all":
105
+ response_text = get_default_relay_device_state()
106
+ else:
107
+ response_text = get_default_relay_device_relay_state(relay_number)
108
+ return {"status": "success", "relay_state": response_text}
109
+ else:
110
+ raise HTTPException(status_code=400, detail="Failed to set relay state. Check command.")
111
+ except Exception as e:
112
+ logging.error(f"Error in default_relay_control: {e}")
113
+ raise HTTPException(status_code=500, detail="Internal Server Error")
114
+
115
+ if __name__ == "__main__":
116
+ uvicorn.run(app, host=socket.getfqdn(), port=9400)
@@ -0,0 +1,197 @@
1
+ """
2
+ This module provides functions to interact with a USB relay device using command-line commands.
3
+ It allows users to get and set the state of the relay device, as well as retrieve information about the relay device's status.
4
+ """
5
+
6
+ import os
7
+ import platform
8
+ import subprocess
9
+ from typing import Optional, Tuple, List
10
+
11
+ def get_platform_and_architecture() -> Tuple[str, str]:
12
+ """
13
+ Get the current system platform and architecture.
14
+
15
+ Returns:
16
+ tuple: (system, architecture), both lowercase strings.
17
+ """
18
+ return platform.system().lower(), platform.architecture()[0].lower()
19
+
20
+ def get_bin_path() -> str:
21
+ """
22
+ Get the absolute path to the package's binary folder.
23
+
24
+ Returns:
25
+ str: Path to the binary folder.
26
+ """
27
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'hid_usb_relay_bin')
28
+
29
+ def get_relay_path(file_name: str) -> str:
30
+ """
31
+ Build the path to a relay binary/library for the current platform and architecture.
32
+
33
+ Args:
34
+ file_name (str): Name of the binary/library file.
35
+
36
+ Returns:
37
+ str: Full path to the file.
38
+
39
+ Raises:
40
+ OSError: If the system platform is unsupported.
41
+ """
42
+ bin_dir = get_bin_path()
43
+ system, arch = get_platform_and_architecture()
44
+ if system not in ['windows', 'linux']:
45
+ raise OSError(f'Unsupported system platform: {system}')
46
+ return os.path.join(bin_dir, system, arch, file_name)
47
+
48
+ def get_relay_executable() -> str:
49
+ """
50
+ Get the path to the relay command-line executable for the current platform.
51
+
52
+ Returns:
53
+ str: Full path to the relay executable.
54
+ """
55
+ exe_name = "hidusb-relay-cmd.exe" if platform.system().lower() == 'windows' else "hidusb-relay-cmd"
56
+ return get_relay_path(exe_name)
57
+
58
+ def get_relay_library() -> str:
59
+ """
60
+ Get the path to the relay library for the current platform.
61
+
62
+ Returns:
63
+ str: Full path to the relay library.
64
+ """
65
+ lib_name = "USB_RELAY_DEVICE.dll" if platform.system().lower() == 'windows' else "usb_relay_device.so"
66
+ return get_relay_path(lib_name)
67
+
68
+ def run_command(command: List[str]) -> Optional[str]:
69
+ """
70
+ Run a command using subprocess and return its output.
71
+
72
+ Args:
73
+ command (List[str]): Command and arguments as a list.
74
+
75
+ Returns:
76
+ Optional[str]: Output string if successful, None otherwise.
77
+ """
78
+ process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
79
+ if process.returncode == 0:
80
+ return process.stdout.strip()
81
+ print(f"Error executing command: {process.stderr}")
82
+ return None
83
+
84
+ def get_default_relay_device_state() -> Optional[List[str]]:
85
+ """
86
+ Get the status of the default relay device.
87
+
88
+ Returns:
89
+ Optional[List[str]]: List of relay states, or None on error.
90
+ """
91
+ output = run_command([get_relay_executable(), "STATUS"])
92
+ return output.split(':')[-1].strip().split(' ') if output else None
93
+
94
+ def set_default_relay_device_state(relay_state: str) -> bool:
95
+ """
96
+ Set all relays on the default device to a given state.
97
+
98
+ Args:
99
+ relay_state (str): "ON" or "OFF".
100
+
101
+ Returns:
102
+ bool: True if successful, False otherwise.
103
+ """
104
+ return run_command([get_relay_executable(), relay_state, "ALL"]) is not None
105
+
106
+ def get_relay_device_state(relay_id: str) -> Optional[List[str]]:
107
+ """
108
+ Get the status of a specific relay device by ID.
109
+
110
+ Args:
111
+ relay_id (str): Relay device ID.
112
+
113
+ Returns:
114
+ Optional[List[str]]: List of relay states, or None on error.
115
+ """
116
+ output = run_command([get_relay_executable(), f"id={relay_id}", "STATUS"])
117
+ return output.split(':')[-1].strip().split(' ') if output else None
118
+
119
+ def set_relay_device_state(relay_id: str, relay_state: str) -> bool:
120
+ """
121
+ Set all relays on a specific device to a given state.
122
+
123
+ Args:
124
+ relay_id (str): Relay device ID.
125
+ relay_state (str): "ON" or "OFF".
126
+
127
+ Returns:
128
+ bool: True if successful, False otherwise.
129
+ """
130
+ return run_command([get_relay_executable(), f"id={relay_id}", relay_state, "ALL"]) is not None
131
+
132
+ def get_all_relay_device_state() -> Optional[str]:
133
+ """
134
+ Get the status of all connected relay devices.
135
+
136
+ Returns:
137
+ Optional[str]: Status string, or None on error.
138
+ """
139
+ return run_command([get_relay_executable(), "ENUM"])
140
+
141
+ def get_relay_device_relay_state(relay_id: str, relay_number: str) -> Optional[str]:
142
+ """
143
+ Get the state of a specific relay on a specific device.
144
+
145
+ Args:
146
+ relay_id (str): Relay device ID.
147
+ relay_number (str): Relay number as string (e.g., "1").
148
+
149
+ Returns:
150
+ Optional[str]: State ("ON"/"OFF") or None on error.
151
+ """
152
+ states = get_relay_device_state(relay_id)
153
+ if states:
154
+ return states[int(relay_number) - 1].split('=')[-1]
155
+ return None
156
+
157
+ def set_relay_device_relay_state(relay_id: str, relay_number: str, relay_state: str) -> bool:
158
+ """
159
+ Set the state of a specific relay on a specific device.
160
+
161
+ Args:
162
+ relay_id (str): Relay device ID.
163
+ relay_number (str): Relay number as string (e.g., "1").
164
+ relay_state (str): "ON" or "OFF".
165
+
166
+ Returns:
167
+ bool: True if successful, False otherwise.
168
+ """
169
+ return run_command([get_relay_executable(), f"id={relay_id}", relay_state, relay_number]) is not None
170
+
171
+ def get_default_relay_device_relay_state(relay_number: str) -> Optional[str]:
172
+ """
173
+ Get the state of a specific relay on the default device.
174
+
175
+ Args:
176
+ relay_number (str): Relay number as string (e.g., "1").
177
+
178
+ Returns:
179
+ Optional[str]: State ("ON"/"OFF") or None on error.
180
+ """
181
+ states = get_default_relay_device_state()
182
+ if states:
183
+ return states[int(relay_number) - 1].split('=')[-1]
184
+ return None
185
+
186
+ def set_default_relay_device_relay_state(relay_number: str, relay_state: str) -> bool:
187
+ """
188
+ Set the state of a specific relay on the default device.
189
+
190
+ Args:
191
+ relay_number (str): Relay number as string (e.g., "1").
192
+ relay_state (str): "ON" or "OFF".
193
+
194
+ Returns:
195
+ bool: True if successful, False otherwise.
196
+ """
197
+ return run_command([get_relay_executable(), relay_state, relay_number]) is not None
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.3
2
+ Name: hid-usb-relay
3
+ Version: 25.0.0
4
+ Summary: hid based usb relay package
5
+ Keywords: Python,HID,USB,RELAY
6
+ Author: chaitu-ycr
7
+ Author-email: chaitu-ycr <chaitu.ycr@gmail.com>
8
+ License: MIT License
9
+
10
+ Copyright (c) 2025 chaitu-ycr
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ Classifier: Programming Language :: Python :: 3.10
30
+ Classifier: Programming Language :: Python :: 3.11
31
+ Classifier: Programming Language :: Python :: 3.12
32
+ Classifier: Programming Language :: Python :: 3.13
33
+ Classifier: Programming Language :: Python :: 3.14
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: Microsoft :: Windows
36
+ Requires-Dist: gradio
37
+ Requires-Dist: fastapi[standard]
38
+ Requires-Python: >=3.10, <=3.14
39
+ Project-URL: documentation, https://chaitu-ycr.github.io/automotive-test-kit/packages/hid_usb_relay
40
+ Project-URL: homepage, https://github.com/chaitu-ycr/automotive-test-kit/tree/main/packages/hid_usb_relay
41
+ Project-URL: repository, https://github.com/chaitu-ycr/automotive-test-kit
42
+ Description-Content-Type: text/markdown
43
+
44
+ # hid_usb_relay
45
+
46
+ hid based usb relay package
47
+
48
+ ## [source manual](https://chaitu-ycr.github.io/automotive-test-kit/packages/hid_usb_relay/#source-manual)
@@ -0,0 +1,15 @@
1
+ hid_usb_relay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ hid_usb_relay/hid_usb_relay_bin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ hid_usb_relay/hid_usb_relay_bin/linux/32bit/hidusb-relay-cmd,sha256=kZpUbPucCsGzHXizusMupgSMhfJhj9-As1E5gzLFtX4,17051
4
+ hid_usb_relay/hid_usb_relay_bin/linux/64bit/hidusb-relay-cmd,sha256=RvWPyw5o0TPBqLcjZfc3iCBHodM9k_l5NrstWDTnr90,18759
5
+ hid_usb_relay/hid_usb_relay_bin/windows/32bit/GUIapp.exe,sha256=KYPvhXRzh8XcG2_T01a9F1rDTNZ2lSvF6alzbVu_INY,61440
6
+ hid_usb_relay/hid_usb_relay_bin/windows/32bit/USB_RELAY_DEVICE.dll,sha256=O-WWBlxyNJzuvJswQ_rnFTkg6FeWR-LBqsLfPCBqNWU,52736
7
+ hid_usb_relay/hid_usb_relay_bin/windows/32bit/hidusb-relay-cmd.exe,sha256=uhuw_pnRRmQAcbZHC9fwwTbL8fwfyN6jMfXsNHB_GAk,66048
8
+ hid_usb_relay/hid_usb_relay_bin/windows/64bit/GUIapp.exe,sha256=HxUtZEguzAV41H3CQfAG6EbiOVChJxgjWj_0IHCaJvI,69632
9
+ hid_usb_relay/hid_usb_relay_bin/windows/64bit/USB_RELAY_DEVICE.dll,sha256=vcbH-kbY6QCWRYGQ-EiRCIoXgIgZlckc0pHXoU9eJIE,86528
10
+ hid_usb_relay/hid_usb_relay_bin/windows/64bit/hidusb-relay-cmd.exe,sha256=wknn0l05jSHsvmwKrFlit2p8gPMbQP3LkV_5gwjmWTs,92672
11
+ hid_usb_relay/rest_api.py,sha256=5HzVPE5WAkVg2M_w7-0YFUvCnsGMTp8pDO91Vg2iI1o,4644
12
+ hid_usb_relay/usb_relay.py,sha256=B5lnTDhMQjjhFzg9sIVeGC-08gy7CEUvm9tP5k4uFVg,6418
13
+ hid_usb_relay-25.0.0.dist-info/WHEEL,sha256=5h_Q-_6zWQhhADpsAD_Xpw7gFbCRK5WjOOEq0nB806Q,79
14
+ hid_usb_relay-25.0.0.dist-info/METADATA,sha256=fw-zZoVFpzMJELZcZsZqMe8W9mCb_Y9NymAgiwaYijE,2375
15
+ hid_usb_relay-25.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.8.18
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any