zspdu 0.0.1__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.
zspdu-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ganesan Selvaraj
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
zspdu-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: zspdu
3
+ Version: 0.0.1
4
+ Summary: Control ZSPDU smart power distribution unit via serial port
5
+ Home-page: https://github.com/ganesanluna/zspdu
6
+ Author: Ganesan Selvaraj
7
+ Author-email: ganesanluna@yahoo.in
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: pyserial
15
+ Requires-Dist: pydantic
16
+ Requires-Dist: robotframework
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: home-page
23
+ Dynamic: license
24
+ Dynamic: license-file
25
+ Dynamic: requires-dist
26
+ Dynamic: requires-python
27
+ Dynamic: summary
28
+
29
+ # zspdu
30
+
31
+ **zspdu** is a Python package and Robot Framework library for controlling Smart PDUs (Power Distribution Units) via USB serial interfaces.
32
+ It provides both a command‑line interface (CLI) and Robot Framework keywords for automation.
33
+
34
+ ---
35
+
36
+ ## Features
37
+
38
+ - List available serial ports
39
+ - Open and switch between ports
40
+ - Turn individual sockets ON/OFF
41
+ - Turn all sockets ON/OFF
42
+ - Read current measurements
43
+ - Close connections
44
+ - Usable as:
45
+ - **CLI tool** (`zspdu`)
46
+ - **Robot Framework library** (`Library zspdu`)
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ Clone the repository and install in editable mode:
53
+
54
+ git clone https://github.com/ganesanluna/zspdu.git
55
+ cd zspdu
56
+ pip install -e .
57
+
58
+ This will install the package and register the `zspdu` CLI command.
59
+
60
+ ---
61
+
62
+ ## Command Line Usage
63
+
64
+ zspdu -l # List all available serial ports
65
+ zspdu -o /dev/ttyUSB0 # Open specific port
66
+ zspdu -s /dev/ttyUSB1 # Switch to another port
67
+ zspdu --on 3 # Turn ON socket 3
68
+ zspdu --off 2 # Turn OFF socket 2
69
+ zspdu --on-all # Turn ON all sockets
70
+ zspdu --off-all # Turn OFF all sockets
71
+ zspdu -c # Close current port
72
+ zspdu -v # Show version
73
+
74
+ Running `zspdu` without arguments will display the help message.
75
+
76
+ ---
77
+
78
+ ## Robot Framework Usage
79
+
80
+ Import the library in your `.robot` test file:
81
+ ```robot
82
+ *** Settings ***
83
+ Library zspdu
84
+
85
+ *** Test Cases ***
86
+ Control PDU
87
+ Turn Socket On 1
88
+ ${current}= Read Current
89
+ Log Current reading: ${current}
90
+ Turn Socket Off 1
91
+ Close PDU Connection
92
+ ```
93
+ You can also pass arguments when importing:
94
+ ``` robot
95
+ *** Settings ***
96
+ Library zspdu port=/dev/ttyUSB1 baudrate=9600 sockets=4
97
+ ```
98
+ ---
99
+
100
+ ## Device Information (from ZS12x0 USB PDU)
101
+
102
+ ### Variants
103
+ - **ZS1220**: 8‑port USB PDU (Part Number: ZS-PDU8-USB-P1B)
104
+
105
+ ### Specifications
106
+ - Output Power Sockets: 8
107
+ - Power Supply: 240VAC, 15A
108
+ - Fuse Rating: 15A
109
+ - Max Current per Socket: 13A
110
+ - Total Load Capacity: 3kVA
111
+ - Relay Switching Life Expectancy: 50,000 cycles
112
+ - Current Sensing Range: up to 15A
113
+ - Control Port: USB2.0 Type‑B
114
+
115
+ ### Serial Port Settings
116
+ - Baud Rate: 115200
117
+ - Data Bits: 8
118
+ - Stop Bit: 1
119
+ - Parity: None
120
+ - Flow Control: None
121
+
122
+ ---
123
+
124
+ ## Usage: Command line options
125
+ ``` text
126
+ $ zspdu --help
127
+ usage: zspdu [-h] [-v] [-l | -o PORT | -s PORT | --on SOCKET | --off SOCKET | --on-all | --off-all | -c]
128
+
129
+ Smart PDU control via serial interface
130
+
131
+ options:
132
+ -h, --help show this help message and exit
133
+ -v, --version show program's version number and exit
134
+ -l, --list List all available serial ports
135
+ -o PORT, --open PORT Open specific serial port
136
+ -s PORT, --switch PORT
137
+ Switch to another serial port
138
+ --on SOCKET Turn ON specific power socket
139
+ --off SOCKET Turn OFF specific power socket
140
+ --on-all Turn ON all power sockets
141
+ --off-all Turn OFF all power sockets
142
+ -c, --close Close current port
143
+ ```
144
+
145
+ > Current version 1.0.0, this software version supported only for linux and supported single pdu support with default port /dev/ttyUSB0.
146
+
147
+ ---
148
+
149
+ ## Development
150
+
151
+ Folder structure:
152
+ ``` text
153
+ .
154
+ ├── src/
155
+ │ └── zspdu/
156
+ │ ├── __init__.py
157
+ │ ├── core.py
158
+ │ ├── utils.py
159
+ │ └── cli.py
160
+ ├── LICENSE
161
+ ├── README.md
162
+ ├── pyproject.toml
163
+ ├── requirements.txt
164
+ └── setup.py
165
+ ```
166
+ ---
167
+
168
+ ## License
169
+
170
+ MIT License
171
+ Copyright (c) 2026 Ganesan Selvaraj
172
+
173
+ Permission is hereby granted, free of charge, to any person obtaining a copy
174
+ of this software and associated documentation files (the "Software"), to deal
175
+ in the Software without restriction, including without limitation the rights
176
+ to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
177
+ copies of the Software, and to permit persons to whom the Software is
178
+ furnished to do so, subject to the following conditions:
179
+
180
+ The above copyright notice and this permission notice shall be included in all
181
+ copies or substantial portions of the Software.
182
+
183
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
184
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
186
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
187
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
188
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
189
+ SOFTWARE.
zspdu-0.0.1/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # zspdu
2
+
3
+ **zspdu** is a Python package and Robot Framework library for controlling Smart PDUs (Power Distribution Units) via USB serial interfaces.
4
+ It provides both a command‑line interface (CLI) and Robot Framework keywords for automation.
5
+
6
+ ---
7
+
8
+ ## Features
9
+
10
+ - List available serial ports
11
+ - Open and switch between ports
12
+ - Turn individual sockets ON/OFF
13
+ - Turn all sockets ON/OFF
14
+ - Read current measurements
15
+ - Close connections
16
+ - Usable as:
17
+ - **CLI tool** (`zspdu`)
18
+ - **Robot Framework library** (`Library zspdu`)
19
+
20
+ ---
21
+
22
+ ## Installation
23
+
24
+ Clone the repository and install in editable mode:
25
+
26
+ git clone https://github.com/ganesanluna/zspdu.git
27
+ cd zspdu
28
+ pip install -e .
29
+
30
+ This will install the package and register the `zspdu` CLI command.
31
+
32
+ ---
33
+
34
+ ## Command Line Usage
35
+
36
+ zspdu -l # List all available serial ports
37
+ zspdu -o /dev/ttyUSB0 # Open specific port
38
+ zspdu -s /dev/ttyUSB1 # Switch to another port
39
+ zspdu --on 3 # Turn ON socket 3
40
+ zspdu --off 2 # Turn OFF socket 2
41
+ zspdu --on-all # Turn ON all sockets
42
+ zspdu --off-all # Turn OFF all sockets
43
+ zspdu -c # Close current port
44
+ zspdu -v # Show version
45
+
46
+ Running `zspdu` without arguments will display the help message.
47
+
48
+ ---
49
+
50
+ ## Robot Framework Usage
51
+
52
+ Import the library in your `.robot` test file:
53
+ ```robot
54
+ *** Settings ***
55
+ Library zspdu
56
+
57
+ *** Test Cases ***
58
+ Control PDU
59
+ Turn Socket On 1
60
+ ${current}= Read Current
61
+ Log Current reading: ${current}
62
+ Turn Socket Off 1
63
+ Close PDU Connection
64
+ ```
65
+ You can also pass arguments when importing:
66
+ ``` robot
67
+ *** Settings ***
68
+ Library zspdu port=/dev/ttyUSB1 baudrate=9600 sockets=4
69
+ ```
70
+ ---
71
+
72
+ ## Device Information (from ZS12x0 USB PDU)
73
+
74
+ ### Variants
75
+ - **ZS1220**: 8‑port USB PDU (Part Number: ZS-PDU8-USB-P1B)
76
+
77
+ ### Specifications
78
+ - Output Power Sockets: 8
79
+ - Power Supply: 240VAC, 15A
80
+ - Fuse Rating: 15A
81
+ - Max Current per Socket: 13A
82
+ - Total Load Capacity: 3kVA
83
+ - Relay Switching Life Expectancy: 50,000 cycles
84
+ - Current Sensing Range: up to 15A
85
+ - Control Port: USB2.0 Type‑B
86
+
87
+ ### Serial Port Settings
88
+ - Baud Rate: 115200
89
+ - Data Bits: 8
90
+ - Stop Bit: 1
91
+ - Parity: None
92
+ - Flow Control: None
93
+
94
+ ---
95
+
96
+ ## Usage: Command line options
97
+ ``` text
98
+ $ zspdu --help
99
+ usage: zspdu [-h] [-v] [-l | -o PORT | -s PORT | --on SOCKET | --off SOCKET | --on-all | --off-all | -c]
100
+
101
+ Smart PDU control via serial interface
102
+
103
+ options:
104
+ -h, --help show this help message and exit
105
+ -v, --version show program's version number and exit
106
+ -l, --list List all available serial ports
107
+ -o PORT, --open PORT Open specific serial port
108
+ -s PORT, --switch PORT
109
+ Switch to another serial port
110
+ --on SOCKET Turn ON specific power socket
111
+ --off SOCKET Turn OFF specific power socket
112
+ --on-all Turn ON all power sockets
113
+ --off-all Turn OFF all power sockets
114
+ -c, --close Close current port
115
+ ```
116
+
117
+ > Current version 1.0.0, this software version supported only for linux and supported single pdu support with default port /dev/ttyUSB0.
118
+
119
+ ---
120
+
121
+ ## Development
122
+
123
+ Folder structure:
124
+ ``` text
125
+ .
126
+ ├── src/
127
+ │ └── zspdu/
128
+ │ ├── __init__.py
129
+ │ ├── core.py
130
+ │ ├── utils.py
131
+ │ └── cli.py
132
+ ├── LICENSE
133
+ ├── README.md
134
+ ├── pyproject.toml
135
+ ├── requirements.txt
136
+ └── setup.py
137
+ ```
138
+ ---
139
+
140
+ ## License
141
+
142
+ MIT License
143
+ Copyright (c) 2026 Ganesan Selvaraj
144
+
145
+ Permission is hereby granted, free of charge, to any person obtaining a copy
146
+ of this software and associated documentation files (the "Software"), to deal
147
+ in the Software without restriction, including without limitation the rights
148
+ to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
149
+ copies of the Software, and to permit persons to whom the Software is
150
+ furnished to do so, subject to the following conditions:
151
+
152
+ The above copyright notice and this permission notice shall be included in all
153
+ copies or substantial portions of the Software.
154
+
155
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
157
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
158
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
159
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
160
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
161
+ SOFTWARE.
zspdu-0.0.1/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
zspdu-0.0.1/setup.py ADDED
@@ -0,0 +1,34 @@
1
+ from setuptools import setup, find_packages
2
+ import pathlib
3
+
4
+ here = pathlib.Path(__file__).parent
5
+ long_description = (here / "README.md").read_text(encoding="utf-8")
6
+
7
+ setup(
8
+ name="zspdu",
9
+ version="0.0.1", # bump version before re-upload
10
+ description="Control ZSPDU smart power distribution unit via serial port",
11
+ long_description=long_description,
12
+ long_description_content_type="text/markdown", # tells PyPI to render Markdown
13
+ author="Ganesan Selvaraj",
14
+ author_email="ganesanluna@yahoo.in",
15
+ url="https://github.com/ganesanluna/zspdu",
16
+ license="MIT",
17
+ packages=find_packages(where="src"),
18
+ package_dir={"": "src"},
19
+ install_requires=[
20
+ "pyserial",
21
+ "pydantic",
22
+ "robotframework"
23
+ ],
24
+ entry_points={
25
+ "console_scripts": [
26
+ "zspdu=zspdu.cli:main",
27
+ ],
28
+ },
29
+ classifiers=[
30
+ "Programming Language :: Python :: 3",
31
+ "Operating System :: OS Independent",
32
+ ],
33
+ python_requires=">=3.8",
34
+ )
@@ -0,0 +1,12 @@
1
+ from .core import ZSPDU, PDUConfig
2
+ from .utils import get_default_port
3
+
4
+ class zspdu(ZSPDU):
5
+ """Robot Framework library wrapper for ZSPDU."""
6
+
7
+ def __init__(self, port=None, baudrate=115200, timeout=3, sockets=8):
8
+ # Only store config, don’t open port yet
9
+ port = port or get_default_port()
10
+ self.config = PDUConfig(port=port, baudrate=baudrate, timeout=timeout, sockets=sockets)
11
+ self.ser = None
12
+ self.sockets = sockets
@@ -0,0 +1,49 @@
1
+ import argparse
2
+ from .utils import get_serial_ports, get_default_port
3
+ from .core import PDUConfig, ZSPDU
4
+
5
+ def main():
6
+ parser = argparse.ArgumentParser(
7
+ prog="zspdu",
8
+ description="Smart PDU control via serial interface"
9
+ )
10
+
11
+ parser.add_argument("-v", "--version", action="version", version="zspdu 1.0.0")
12
+
13
+ group = parser.add_mutually_exclusive_group()
14
+ group.add_argument("-l", "--list", action="store_true", help="List all available serial ports")
15
+ group.add_argument("-o", "--open", metavar="PORT", help="Open specific serial port")
16
+ group.add_argument("-s", "--switch", metavar="PORT", help="Switch to another serial port")
17
+ group.add_argument("--on", metavar="SOCKET", type=int, help="Turn ON specific power socket")
18
+ group.add_argument("--off", metavar="SOCKET", type=int, help="Turn OFF specific power socket")
19
+ group.add_argument("--on-all", action="store_true", help="Turn ON all power sockets")
20
+ group.add_argument("--off-all", action="store_true", help="Turn OFF all power sockets")
21
+ group.add_argument("-c", "--close", action="store_true", help="Close current port")
22
+
23
+ args = parser.parse_args()
24
+
25
+ # If no arguments provided, show help
26
+ if not any(vars(args).values()):
27
+ parser.print_help()
28
+ return
29
+
30
+ # Dispatch logic
31
+ if args.list:
32
+ print("Available ports:", get_serial_ports())
33
+ else:
34
+ config = PDUConfig(port=args.open or get_default_port())
35
+ pdu = ZSPDU(config)
36
+
37
+ if args.switch:
38
+ print(pdu.switch_port(args.switch))
39
+ elif args.on is not None:
40
+ print(pdu.port_on(args.on))
41
+ elif args.off is not None:
42
+ print(pdu.port_off(args.off))
43
+ elif args.on_all:
44
+ print(pdu.port_on_all())
45
+ elif args.off_all:
46
+ print(pdu.port_off_all())
47
+ elif args.close:
48
+ pdu.close()
49
+ print("Closed current port")
@@ -0,0 +1,142 @@
1
+ """ System libraries """
2
+ import serial
3
+ import serial.tools.list_ports
4
+ import platform
5
+ from typing import List
6
+ from pydantic import BaseModel, Field, field_validator
7
+ from robot.api.deco import keyword
8
+
9
+
10
+ def get_serial_ports() -> List[str]:
11
+ """
12
+ Return a list of valid serial port device names.
13
+
14
+ Returns:
15
+ List[str]: A list of available serial port device paths
16
+ (e.g., '/dev/ttyUSB0').
17
+ """
18
+ ports: List[str] = []
19
+ for port in sorted(serial.tools.list_ports.comports()):
20
+ if port.description != "n/a" and port.hwid != "n/a":
21
+ ports.append(port.device)
22
+ return ports
23
+
24
+
25
+ def get_default_port() -> str:
26
+ system = platform.system().lower()
27
+ if "linux" in system:
28
+ return "/dev/ttyUSB0"
29
+ elif "windows" in system:
30
+ return "COM5"
31
+ else:
32
+ return "/dev/ttyUSB0"
33
+
34
+
35
+ class PDUConfig(BaseModel):
36
+ port: str = Field(default_factory=get_default_port)
37
+ baudrate: int = Field(default=115200, gt=0)
38
+ timeout: int = Field(default=3, ge=1)
39
+ sockets: int = Field(default=8, ge=1)
40
+
41
+
42
+ class PDUCommand(BaseModel):
43
+ cmd: str
44
+
45
+ @field_validator("cmd")
46
+ def validate_command(cls, v):
47
+ if not v.startswith(("S", "C", "PM")):
48
+ raise ValueError("Invalid PDU command. Must start with S, C, PM.")
49
+ return v
50
+
51
+
52
+ class ZSPDU:
53
+ def __init__(self, config: PDUConfig) -> None:
54
+ self.config = config
55
+ self.sockets: int = config.sockets
56
+ self.ser: serial.Serial | None = None
57
+ self.open_port(config.port)
58
+
59
+ @keyword("Open Port")
60
+ def open_port(self, port: str) -> str:
61
+ """Open a specific serial port."""
62
+ if self.ser and self.ser.is_open:
63
+ self.ser.close()
64
+ try:
65
+ self.ser = serial.Serial(
66
+ port=port,
67
+ baudrate=self.config.baudrate,
68
+ timeout=self.config.timeout
69
+ )
70
+ return f"Opened port {port}"
71
+ except serial.SerialException as e:
72
+ raise RuntimeError(f"Failed to open serial port {port}: {e}")
73
+
74
+ @keyword("Switch Port")
75
+ def switch_port(self, port: str) -> str:
76
+ """Switch to another serial port."""
77
+ return self.open_port(port)
78
+
79
+ @keyword("Send PDU Command")
80
+ def send(self, command: PDUCommand) -> str:
81
+ if not self.ser or not self.ser.is_open:
82
+ raise RuntimeError("Serial port is not open")
83
+ self.ser.write((command.cmd + "\r\n").encode("utf-8"))
84
+ #time.sleep(0.25)
85
+ return self.ser.readline().decode("utf-8", errors="ignore").strip()
86
+
87
+ @keyword("Turn Socket On")
88
+ def port_on(self, n: int) -> str:
89
+ self.send(PDUCommand(cmd=f"S{n}"))
90
+ return f"Power socket {n} is turned ON"
91
+
92
+ @keyword("Turn Socket Off")
93
+ def port_off(self, n: int) -> str:
94
+ self.send(PDUCommand(cmd=f"C{n}"))
95
+ return f"Power socket {n} is turned OFF"
96
+
97
+ @keyword("Turn All Sockets On")
98
+ def port_on_all(self) -> str:
99
+ for i in range(1, self.sockets + 1):
100
+ self.port_on(i)
101
+ return "All power sockets are turned ON"
102
+
103
+ @keyword("Turn All Sockets Off")
104
+ def port_off_all(self) -> str:
105
+ for i in range(1, self.sockets + 1):
106
+ self.port_off(i)
107
+ return "All power sockets are turned OFF"
108
+
109
+ @keyword("Read Current")
110
+ def read_current(self) -> str:
111
+ return self.send(PDUCommand(cmd="PM"))
112
+
113
+ @keyword("Close PDU Connection")
114
+ def close(self) -> None:
115
+ if self.ser and self.ser.is_open:
116
+ self.ser.close()
117
+
118
+
119
+ if __name__ == "__main__":
120
+ try:
121
+ # List available serial ports
122
+ available_ports = get_serial_ports()
123
+ print("Available serial ports:", available_ports)
124
+
125
+ # Use first available port if present, otherwise fallback
126
+ config = PDUConfig(
127
+ port=available_ports[0] if available_ports else "/dev/ttyUSB0",
128
+ baudrate=115200,
129
+ timeout=3,
130
+ sockets=8
131
+ )
132
+
133
+ # Initialize PDU
134
+ pdu = ZSPDU(config)
135
+
136
+ # Turn on socket 1
137
+ print(pdu.port_on(1))
138
+
139
+ pdu.close()
140
+
141
+ except Exception as e:
142
+ print("Error:", e)
@@ -0,0 +1,29 @@
1
+ """ Custom library """
2
+ import serial.tools.list_ports
3
+
4
+ """ system library """
5
+ import platform
6
+ from typing import List
7
+
8
+ def get_serial_ports() -> List[str]:
9
+ """
10
+ Return a list of valid serial port device names.
11
+
12
+ Returns:
13
+ List[str]: A list of available serial port device paths
14
+ (e.g., '/dev/ttyUSB0').
15
+ """
16
+ ports: List[str] = []
17
+ for port in sorted(serial.tools.list_ports.comports()):
18
+ if port.description != "n/a" and port.hwid != "n/a":
19
+ ports.append(port.device)
20
+ return ports
21
+
22
+ def get_default_port() -> str:
23
+ system = platform.system().lower()
24
+ if "linux" in system:
25
+ return "/dev/ttyUSB0"
26
+ elif "windows" in system:
27
+ return "COM5"
28
+ else:
29
+ return "/dev/ttyUSB0"
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: zspdu
3
+ Version: 0.0.1
4
+ Summary: Control ZSPDU smart power distribution unit via serial port
5
+ Home-page: https://github.com/ganesanluna/zspdu
6
+ Author: Ganesan Selvaraj
7
+ Author-email: ganesanluna@yahoo.in
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: pyserial
15
+ Requires-Dist: pydantic
16
+ Requires-Dist: robotframework
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: home-page
23
+ Dynamic: license
24
+ Dynamic: license-file
25
+ Dynamic: requires-dist
26
+ Dynamic: requires-python
27
+ Dynamic: summary
28
+
29
+ # zspdu
30
+
31
+ **zspdu** is a Python package and Robot Framework library for controlling Smart PDUs (Power Distribution Units) via USB serial interfaces.
32
+ It provides both a command‑line interface (CLI) and Robot Framework keywords for automation.
33
+
34
+ ---
35
+
36
+ ## Features
37
+
38
+ - List available serial ports
39
+ - Open and switch between ports
40
+ - Turn individual sockets ON/OFF
41
+ - Turn all sockets ON/OFF
42
+ - Read current measurements
43
+ - Close connections
44
+ - Usable as:
45
+ - **CLI tool** (`zspdu`)
46
+ - **Robot Framework library** (`Library zspdu`)
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ Clone the repository and install in editable mode:
53
+
54
+ git clone https://github.com/ganesanluna/zspdu.git
55
+ cd zspdu
56
+ pip install -e .
57
+
58
+ This will install the package and register the `zspdu` CLI command.
59
+
60
+ ---
61
+
62
+ ## Command Line Usage
63
+
64
+ zspdu -l # List all available serial ports
65
+ zspdu -o /dev/ttyUSB0 # Open specific port
66
+ zspdu -s /dev/ttyUSB1 # Switch to another port
67
+ zspdu --on 3 # Turn ON socket 3
68
+ zspdu --off 2 # Turn OFF socket 2
69
+ zspdu --on-all # Turn ON all sockets
70
+ zspdu --off-all # Turn OFF all sockets
71
+ zspdu -c # Close current port
72
+ zspdu -v # Show version
73
+
74
+ Running `zspdu` without arguments will display the help message.
75
+
76
+ ---
77
+
78
+ ## Robot Framework Usage
79
+
80
+ Import the library in your `.robot` test file:
81
+ ```robot
82
+ *** Settings ***
83
+ Library zspdu
84
+
85
+ *** Test Cases ***
86
+ Control PDU
87
+ Turn Socket On 1
88
+ ${current}= Read Current
89
+ Log Current reading: ${current}
90
+ Turn Socket Off 1
91
+ Close PDU Connection
92
+ ```
93
+ You can also pass arguments when importing:
94
+ ``` robot
95
+ *** Settings ***
96
+ Library zspdu port=/dev/ttyUSB1 baudrate=9600 sockets=4
97
+ ```
98
+ ---
99
+
100
+ ## Device Information (from ZS12x0 USB PDU)
101
+
102
+ ### Variants
103
+ - **ZS1220**: 8‑port USB PDU (Part Number: ZS-PDU8-USB-P1B)
104
+
105
+ ### Specifications
106
+ - Output Power Sockets: 8
107
+ - Power Supply: 240VAC, 15A
108
+ - Fuse Rating: 15A
109
+ - Max Current per Socket: 13A
110
+ - Total Load Capacity: 3kVA
111
+ - Relay Switching Life Expectancy: 50,000 cycles
112
+ - Current Sensing Range: up to 15A
113
+ - Control Port: USB2.0 Type‑B
114
+
115
+ ### Serial Port Settings
116
+ - Baud Rate: 115200
117
+ - Data Bits: 8
118
+ - Stop Bit: 1
119
+ - Parity: None
120
+ - Flow Control: None
121
+
122
+ ---
123
+
124
+ ## Usage: Command line options
125
+ ``` text
126
+ $ zspdu --help
127
+ usage: zspdu [-h] [-v] [-l | -o PORT | -s PORT | --on SOCKET | --off SOCKET | --on-all | --off-all | -c]
128
+
129
+ Smart PDU control via serial interface
130
+
131
+ options:
132
+ -h, --help show this help message and exit
133
+ -v, --version show program's version number and exit
134
+ -l, --list List all available serial ports
135
+ -o PORT, --open PORT Open specific serial port
136
+ -s PORT, --switch PORT
137
+ Switch to another serial port
138
+ --on SOCKET Turn ON specific power socket
139
+ --off SOCKET Turn OFF specific power socket
140
+ --on-all Turn ON all power sockets
141
+ --off-all Turn OFF all power sockets
142
+ -c, --close Close current port
143
+ ```
144
+
145
+ > Current version 1.0.0, this software version supported only for linux and supported single pdu support with default port /dev/ttyUSB0.
146
+
147
+ ---
148
+
149
+ ## Development
150
+
151
+ Folder structure:
152
+ ``` text
153
+ .
154
+ ├── src/
155
+ │ └── zspdu/
156
+ │ ├── __init__.py
157
+ │ ├── core.py
158
+ │ ├── utils.py
159
+ │ └── cli.py
160
+ ├── LICENSE
161
+ ├── README.md
162
+ ├── pyproject.toml
163
+ ├── requirements.txt
164
+ └── setup.py
165
+ ```
166
+ ---
167
+
168
+ ## License
169
+
170
+ MIT License
171
+ Copyright (c) 2026 Ganesan Selvaraj
172
+
173
+ Permission is hereby granted, free of charge, to any person obtaining a copy
174
+ of this software and associated documentation files (the "Software"), to deal
175
+ in the Software without restriction, including without limitation the rights
176
+ to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
177
+ copies of the Software, and to permit persons to whom the Software is
178
+ furnished to do so, subject to the following conditions:
179
+
180
+ The above copyright notice and this permission notice shall be included in all
181
+ copies or substantial portions of the Software.
182
+
183
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
184
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
186
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
187
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
188
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
189
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ src/zspdu/__init__.py
5
+ src/zspdu/cli.py
6
+ src/zspdu/core.py
7
+ src/zspdu/utils.py
8
+ src/zspdu.egg-info/PKG-INFO
9
+ src/zspdu.egg-info/SOURCES.txt
10
+ src/zspdu.egg-info/dependency_links.txt
11
+ src/zspdu.egg-info/entry_points.txt
12
+ src/zspdu.egg-info/requires.txt
13
+ src/zspdu.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ zspdu = zspdu.cli:main
@@ -0,0 +1,3 @@
1
+ pyserial
2
+ pydantic
3
+ robotframework
@@ -0,0 +1 @@
1
+ zspdu