hackerbot 0.2.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.
- hackerbot/__init__.py +33 -0
- hackerbot/arm/__init__.py +77 -0
- hackerbot/arm/gripper.py +55 -0
- hackerbot/base/__init__.py +223 -0
- hackerbot/base/maps.py +147 -0
- hackerbot/core.py +120 -0
- hackerbot/examples/keyboard_teleop_examples/AI_ELITE_teleop.py +219 -0
- hackerbot/examples/keyboard_teleop_examples/AI_PRO_teleop.py +180 -0
- hackerbot/examples/keyboard_teleop_examples/arm_teleop.py +230 -0
- hackerbot/examples/keyboard_teleop_examples/base_teleop.py +206 -0
- hackerbot/examples/keyboard_teleop_examples/head_teleop.py +170 -0
- hackerbot/head/__init__.py +61 -0
- hackerbot/head/eyes.py +41 -0
- hackerbot/utils/hackerbot_helper.py +142 -0
- hackerbot/utils/serial_helper.py +156 -0
- hackerbot-0.2.0.dist-info/METADATA +67 -0
- hackerbot-0.2.0.dist-info/RECORD +20 -0
- hackerbot-0.2.0.dist-info/WHEEL +5 -0
- hackerbot-0.2.0.dist-info/licenses/LICENSE +21 -0
- hackerbot-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2025 Hackerbot Industries LLC
|
3
|
+
#
|
4
|
+
# This source code is licensed under the MIT license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
#
|
7
|
+
# Created By: Allen Chien
|
8
|
+
# Created: April 2025
|
9
|
+
# Updated: 2025.04.07
|
10
|
+
#
|
11
|
+
# This module contains the SerialHelper class, which is a base class does the
|
12
|
+
# serial handling. Including sending serial commands, finding serial ports
|
13
|
+
# reading serial outputs.
|
14
|
+
#
|
15
|
+
# Special thanks to the following for their code contributions to this codebase:
|
16
|
+
# Allen Chien - https://github.com/AllenChienXXX
|
17
|
+
################################################################################
|
18
|
+
|
19
|
+
|
20
|
+
import serial
|
21
|
+
import serial.tools.list_ports
|
22
|
+
import threading
|
23
|
+
import os
|
24
|
+
import json
|
25
|
+
from collections import deque
|
26
|
+
|
27
|
+
class SerialHelper:
|
28
|
+
HOME_DIR = os.environ['HOME']
|
29
|
+
|
30
|
+
LOG_FILE_PATH = os.path.join(HOME_DIR, "hackerbot/logs/serial_log.txt")
|
31
|
+
MAP_DATA_PATH = os.path.join(HOME_DIR, "hackerbot/logs/map_{map_id}.txt")
|
32
|
+
|
33
|
+
# port = '/dev/ttyACM1'
|
34
|
+
def __init__(self, port=None, board="adafruit:samd:adafruit_qt_py_m0", baudrate=230400):
|
35
|
+
self.port = port
|
36
|
+
self.board = board
|
37
|
+
self.baudrate = baudrate
|
38
|
+
self.ser = None
|
39
|
+
self.state = None
|
40
|
+
self.ser_error = None
|
41
|
+
|
42
|
+
self.json_entries = deque(maxlen=10) # Store up to 10 most recent JSON entries
|
43
|
+
|
44
|
+
try:
|
45
|
+
if self.port is None:
|
46
|
+
self.port = self.find_port()
|
47
|
+
self.ser = serial.Serial(port=self.port, baudrate=baudrate, timeout=1)
|
48
|
+
except ConnectionError as e:
|
49
|
+
raise ConnectionError(f"Error initializing main controller: {e}")
|
50
|
+
except serial.SerialException as e:
|
51
|
+
raise ConnectionError(f"Serial connection error: {port}. {e}")
|
52
|
+
except Exception as e:
|
53
|
+
raise RuntimeError(f"Error initializing main controller: {e}")
|
54
|
+
|
55
|
+
self.read_thread_stop_event = threading.Event()
|
56
|
+
self.read_thread = threading.Thread(target=self.read_serial)
|
57
|
+
self.read_thread.daemon = False
|
58
|
+
self.read_thread.start()
|
59
|
+
|
60
|
+
def find_port(self):
|
61
|
+
ports = list(serial.tools.list_ports.comports())
|
62
|
+
for port in ports:
|
63
|
+
if "QT Py" in port.description:
|
64
|
+
return port.device
|
65
|
+
|
66
|
+
raise ConnectionError(f"No Port found for {self.board}, are you using a different board?")
|
67
|
+
|
68
|
+
def get_board_and_port(self):
|
69
|
+
return self.board, self.port
|
70
|
+
|
71
|
+
def send_raw_command(self, command):
|
72
|
+
if self.ser and self.ser.is_open:
|
73
|
+
try:
|
74
|
+
self.ser.write(command.encode('utf-8') + b'\r\n')
|
75
|
+
self.state = command
|
76
|
+
except serial.SerialException as e:
|
77
|
+
raise IOError(f"Error writing to serial port: {e}")
|
78
|
+
else:
|
79
|
+
raise ConnectionError("Serial port is closed or unavailable!")
|
80
|
+
|
81
|
+
def get_state(self):
|
82
|
+
return self.state
|
83
|
+
|
84
|
+
def get_ser_error(self):
|
85
|
+
return self.ser_error
|
86
|
+
|
87
|
+
def read_serial(self):
|
88
|
+
if not self.ser:
|
89
|
+
self.ser_error = "Serial connection not initialized."
|
90
|
+
# raise ConnectionError("Serial connection not initialized.")
|
91
|
+
|
92
|
+
try:
|
93
|
+
while not self.read_thread_stop_event.is_set(): # Check the stop event to exit the loop
|
94
|
+
try:
|
95
|
+
if not self.ser.is_open:
|
96
|
+
self.ser_error = "Serial port is closed or unavailable!"
|
97
|
+
# raise ConnectionError("Serial port is closed or unavailable!")
|
98
|
+
|
99
|
+
if self.ser.in_waiting > 0:
|
100
|
+
response = self.ser.readline().decode('utf-8').strip()
|
101
|
+
if response:
|
102
|
+
# Try to parse the response as JSON
|
103
|
+
try:
|
104
|
+
json_entry = json.loads(response)
|
105
|
+
if json_entry.get("command"): # Only store JSON entries with a "command" key
|
106
|
+
self.json_entries.append(json_entry) # Store the latest JSON entry
|
107
|
+
except json.JSONDecodeError:
|
108
|
+
# If it's not a valid JSON entry, just continue
|
109
|
+
continue
|
110
|
+
except serial.SerialException as e:
|
111
|
+
self.ser_error = f"Serial read error: {e}"
|
112
|
+
# raise IOError(f"Serial read error: {e}")
|
113
|
+
except Exception as e:
|
114
|
+
self.ser_error = f"Unexpected read error: {e}"
|
115
|
+
# raise RuntimeError(f"Unexpected read error: {e}")
|
116
|
+
except PermissionError as e:
|
117
|
+
self.ser_error = f"Permission error: {e}"
|
118
|
+
# raise IOError(f"File write error: {e}")
|
119
|
+
except Exception as e:
|
120
|
+
self.ser_error = f"Unexpected error: {e}"
|
121
|
+
# raise IOError(f"File write error: {e}")
|
122
|
+
|
123
|
+
def get_json_from_command(self, command_filter=None):
|
124
|
+
if command_filter is None:
|
125
|
+
raise ValueError("command_filter cannot be None")
|
126
|
+
if self.json_entries is None or len(self.json_entries) == 0:
|
127
|
+
raise ValueError("No JSON entries found")
|
128
|
+
|
129
|
+
for entry in reversed(self.json_entries):
|
130
|
+
if entry.get("command") == command_filter:
|
131
|
+
if entry.get("success") == "true":
|
132
|
+
return entry
|
133
|
+
raise Exception("Fail to fetch...")
|
134
|
+
raise Exception(f"Command {command_filter} not found in JSON entries")
|
135
|
+
|
136
|
+
def stop_read_thread(self):
|
137
|
+
"""Call this method to stop the serial reading thread."""
|
138
|
+
self.read_thread_stop_event.set()
|
139
|
+
self.read_thread.join() # Wait for the thread to fully terminate
|
140
|
+
|
141
|
+
def disconnect_serial(self):
|
142
|
+
"""Disconnect the serial port and stop the read thread cleanly."""
|
143
|
+
# Stop the reading thread first
|
144
|
+
self.stop_read_thread()
|
145
|
+
|
146
|
+
# Close the serial connection safely
|
147
|
+
if self.ser:
|
148
|
+
try:
|
149
|
+
if self.ser.is_open:
|
150
|
+
self.ser.close()
|
151
|
+
except serial.SerialException as e:
|
152
|
+
raise ConnectionError(f"Error closing serial connection: {e}")
|
153
|
+
except Exception as e:
|
154
|
+
raise RuntimeError(f"Unexpected error while disconnecting serial: {e}")
|
155
|
+
finally:
|
156
|
+
self.ser = None
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: hackerbot
|
3
|
+
Version: 0.2.0
|
4
|
+
Summary: This module contains the setup for the hackerbot python package.
|
5
|
+
Author-email: Allen Chien <allen71090@gmail.com>
|
6
|
+
License-Expression: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/hackerbotindustries/hackerbot-python-package
|
8
|
+
Requires-Python: >=3.11
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
License-File: LICENSE
|
11
|
+
Requires-Dist: pyserial
|
12
|
+
Requires-Dist: pytest
|
13
|
+
Dynamic: license-file
|
14
|
+
|
15
|
+
|
16
|
+
# Hackerbot Python Package
|
17
|
+
|
18
|
+
Hackerbot python package (`hackerbot-python-package`) is a project that includes modules for controlling and managing the Hackerbot system.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Follow these steps to clone the repository and set up the required dependencies.
|
23
|
+
|
24
|
+
### 1. Clone the Repository
|
25
|
+
Use SSH to clone the repository:
|
26
|
+
```bash
|
27
|
+
https://github.com/hackerbotindustries/hackerbot-python-package.git
|
28
|
+
```
|
29
|
+
This will create a directory named `hackerbot-python-package` and download all necessary files.
|
30
|
+
|
31
|
+
### 2. Navigate to the Modules Directory
|
32
|
+
Move into the `hackerbot_modules` directory:
|
33
|
+
```bash
|
34
|
+
cd hackerbot-python-package/
|
35
|
+
```
|
36
|
+
|
37
|
+
### 3. Install Dependencies
|
38
|
+
Install the `hackerbot` package using `pip`:
|
39
|
+
```bash
|
40
|
+
pip install .
|
41
|
+
```
|
42
|
+
This will install the package locally for your Python environment.
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
Once installed, you can import `hackerbot` in your Python scripts:
|
46
|
+
```python
|
47
|
+
import hackerbot
|
48
|
+
```
|
49
|
+
|
50
|
+
### 4. Testing
|
51
|
+
To run the unit tests run:
|
52
|
+
```bash
|
53
|
+
cd tests/unit_tests
|
54
|
+
pytest
|
55
|
+
```
|
56
|
+
|
57
|
+
## Troubleshooting
|
58
|
+
If you run into issues with the installation, try the following:
|
59
|
+
- Ensure you're using a virtual environment:
|
60
|
+
```bash
|
61
|
+
python3 -m venv venv
|
62
|
+
source venv/bin/activate
|
63
|
+
```
|
64
|
+
- Upgrade `pip` before installation:
|
65
|
+
```bash
|
66
|
+
pip install --upgrade pip
|
67
|
+
```
|
@@ -0,0 +1,20 @@
|
|
1
|
+
hackerbot/__init__.py,sha256=fjzBB_VsqCuKJ3yeLdqLSvAQIz9bAMI-KXrUC6ZrscY,1248
|
2
|
+
hackerbot/core.py,sha256=oZKQEUaMn19MnaWNTDFqTZ7lziBEZeSk5CdLXLSLvr0,5521
|
3
|
+
hackerbot/arm/__init__.py,sha256=JdCmTDQ2qk3W8-Alc4mjaQYxHnmH26r0nSy0JFg6J4A,3400
|
4
|
+
hackerbot/arm/gripper.py,sha256=xZux0PZL4vvrJTTKHL7dDsRBfJr4zbmgMaA0uBR1u4s,1986
|
5
|
+
hackerbot/base/__init__.py,sha256=PG2Ykn2MLfobAWClGFnp-AZfh1xVsnbc1nQ8E6Yy6eA,8698
|
6
|
+
hackerbot/base/maps.py,sha256=I_4NdvOMnkHX6-mW43QpDPJ-eVc6npgcBXq99tU7D1g,5916
|
7
|
+
hackerbot/examples/keyboard_teleop_examples/AI_ELITE_teleop.py,sha256=cy9Cp4QSYafvm-5xBoq-ks8tdLJHzMvO_6pRweWLVaU,7832
|
8
|
+
hackerbot/examples/keyboard_teleop_examples/AI_PRO_teleop.py,sha256=Q99v488MncM8uZ0okPzrWihQmLKCufEgbLIIT3Od0ig,5959
|
9
|
+
hackerbot/examples/keyboard_teleop_examples/arm_teleop.py,sha256=GoyhRuqqpqwMdBKMq_pgTsbcuVNfO8sGcJKGNiD6P8k,7730
|
10
|
+
hackerbot/examples/keyboard_teleop_examples/base_teleop.py,sha256=3XpXUWtPeCcsYhffcUMWMI_upkA9VFXB0qoinWpaqvA,6545
|
11
|
+
hackerbot/examples/keyboard_teleop_examples/head_teleop.py,sha256=PfE-VzuaF4-bF0wtziyaTX2SnyKqZmDaNDbM8b-W9gQ,5328
|
12
|
+
hackerbot/head/__init__.py,sha256=fNW1u1Kb5jE7q-UGQgZ511gnHPOjeR_monSm8p9CfNI,2466
|
13
|
+
hackerbot/head/eyes.py,sha256=xqeKMxL12iaa8KQzDlbgbNy3LzcmWm8aXkebztYJ4P8,1370
|
14
|
+
hackerbot/utils/hackerbot_helper.py,sha256=egQPVBBUo52ywsO6jGAGVqhyGLpMPz-b2fgLBb39WSM,4998
|
15
|
+
hackerbot/utils/serial_helper.py,sha256=l7pj32mnoVZN-7foU_FPUxdmZaE43jcMmZRBAGEX8Zc,6457
|
16
|
+
hackerbot-0.2.0.dist-info/licenses/LICENSE,sha256=SCcXH0bf35ISRu_Ks8xEKySHXiqclANLWhBUbVU8VvA,1081
|
17
|
+
hackerbot-0.2.0.dist-info/METADATA,sha256=PvGs4X-ax2hoGDWe12HjmBS55bXcK3MMAgb6mgt8Irg,1714
|
18
|
+
hackerbot-0.2.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
19
|
+
hackerbot-0.2.0.dist-info/top_level.txt,sha256=2n_FStAr1SiI3BV67x7KJHYIOmEwxjUD59zedw2hLkU,10
|
20
|
+
hackerbot-0.2.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Hackerbot Industries LLC
|
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, sublicense, 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.
|
@@ -0,0 +1 @@
|
|
1
|
+
hackerbot
|