CrackNuts 0.1.0__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.

Potentially problematic release.


This version of CrackNuts might be problematic. Click here for more details.

@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.1
2
+ Name: CrackNuts
3
+ Version: 0.1.0
4
+ Summary: A library for nut cracker device.
5
+ Author-email: Dingzb <dingzibiao@gmail.com>
6
+ Maintainer-email: Dingzb <dingzibiao@gmail.com>
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: numpy>=2.0.1
10
+ Requires-Dist: pandas>=2.2.2
11
+ Provides-Extra: test
12
+ Requires-Dist: pytest; extra == "test"
13
+ Provides-Extra: marimo
14
+ Requires-Dist: marimo; extra == "marimo"
15
+
16
+ # CrackNuts
17
+
18
+ TODO
@@ -0,0 +1,3 @@
1
+ # CrackNuts
2
+
3
+ TODO
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools >= 61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "CrackNuts"
7
+ description = "A library for nut cracker device."
8
+ dynamic = ["version"]
9
+ requires-python = ">=3.12"
10
+ readme = "README.md"
11
+ authors = [
12
+ { name = "Dingzb", email = "dingzibiao@gmail.com" }
13
+ ]
14
+ maintainers = [
15
+ { name = "Dingzb", email = "dingzibiao@gmail.com" }
16
+ ]
17
+ dependencies = [
18
+ "numpy >= 2.0.1",
19
+ "pandas >= 2.2.2"
20
+ ]
21
+
22
+ [project.optional-dependencies]
23
+
24
+ test = [
25
+ 'pytest'
26
+ ]
27
+
28
+ marimo = [
29
+ 'marimo'
30
+ ]
31
+
32
+ [tool.setuptools.dynamic]
33
+ version = { attr = "cracknuts.__version__" }
34
+
35
+ [tool.pytest.ini_options]
36
+ minversion = "6.0"
37
+ addopts = "-ra -q"
38
+
39
+ [tool.pdm]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.1
2
+ Name: CrackNuts
3
+ Version: 0.1.0
4
+ Summary: A library for nut cracker device.
5
+ Author-email: Dingzb <dingzibiao@gmail.com>
6
+ Maintainer-email: Dingzb <dingzibiao@gmail.com>
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: numpy>=2.0.1
10
+ Requires-Dist: pandas>=2.2.2
11
+ Provides-Extra: test
12
+ Requires-Dist: pytest; extra == "test"
13
+ Provides-Extra: marimo
14
+ Requires-Dist: marimo; extra == "marimo"
15
+
16
+ # CrackNuts
17
+
18
+ TODO
@@ -0,0 +1,25 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/CrackNuts.egg-info/PKG-INFO
4
+ src/CrackNuts.egg-info/SOURCES.txt
5
+ src/CrackNuts.egg-info/dependency_links.txt
6
+ src/CrackNuts.egg-info/requires.txt
7
+ src/CrackNuts.egg-info/top_level.txt
8
+ src/cracknuts/__init__.py
9
+ src/cracknuts/logger.py
10
+ src/cracknuts/acquisition/__init__.py
11
+ src/cracknuts/acquisition/acquisition.py
12
+ src/cracknuts/cracker/__init__.py
13
+ src/cracknuts/cracker/abs_cracker.py
14
+ src/cracknuts/cracker/basic_cracker.py
15
+ src/cracknuts/cracker/protocol.py
16
+ src/cracknuts/solver/__init__.py
17
+ src/cracknuts/solver/trace.py
18
+ src/cracknuts/support/__init__.py
19
+ src/cracknuts/support/marimo/__init__.py
20
+ src/cracknuts/support/marimo/cracker_panel.py
21
+ src/cracknuts/support/marimo/ui/__init__.py
22
+ src/cracknuts/support/marimo/ui/cracker_panel.py
23
+ src/cracknuts/utils/__init__.py
24
+ src/cracknuts/utils/hex_util.py
25
+ tests/test_1.py
@@ -0,0 +1,8 @@
1
+ numpy>=2.0.1
2
+ pandas>=2.2.2
3
+
4
+ [marimo]
5
+ marimo
6
+
7
+ [test]
8
+ pytest
@@ -0,0 +1 @@
1
+ cracknuts
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
File without changes
@@ -0,0 +1,214 @@
1
+ import abc
2
+ import datetime
3
+ import threading
4
+ import time
5
+ import typing
6
+
7
+ import numpy as np
8
+ import zarr
9
+
10
+ from cracknuts import logger
11
+ from cracknuts.cracker.abs_cracker import AbsCracker
12
+
13
+
14
+ class Acquisition(abc.ABC):
15
+
16
+ def __init__(self, cracker: AbsCracker):
17
+ self._logger = logger.get_logger(self)
18
+ self._cracker = cracker
19
+ self._last_wave: np.ndarray | None = np.array([np.zeros(1000)])
20
+ self._running = False
21
+ self._trace_count = 1
22
+ self._on_wave_loaded_callback: typing.Callable = typing.Callable[[np.ndarray], None]
23
+ self._trigger_judge_wait_time: float = 0.2 # second
24
+ self._trigger_judge_timeout: float = 2000000 # microsecond
25
+
26
+ def on_wave_loaded(self, callback: typing.Callable[[np.ndarray], None]) -> None:
27
+ self._on_wave_loaded_callback = callback
28
+
29
+ def run(self, count=1):
30
+ self._logger.debug('Start run mode.')
31
+ self._run(save_data=True, count=count)
32
+
33
+ def run_sync(self, count=1):
34
+ self._do_run(save_data=True, count=count)
35
+
36
+ def test(self, count=1):
37
+ self._logger.debug('Start test mode.')
38
+ self._run(count=count)
39
+
40
+ def stop(self):
41
+ self._running = False
42
+
43
+ def _run(self, save_data: bool = False, count=1):
44
+ threading.Thread(target=self._do_run, kwargs={'save_data': save_data, 'count': count}).start()
45
+
46
+ def _do_run(self, save_data: bool = False, count=1):
47
+
48
+ self._running = True
49
+ # self.connect_scrat()
50
+ # self.config_cracker()
51
+ # self.connect_scrat()
52
+ # self.config_scrat()
53
+ # init
54
+ self._trace_count = count
55
+ self.pre_init()
56
+ self.init() # self.transfer() 用户
57
+ self.save_dataset()
58
+ self.post_init()
59
+
60
+ self._loop()
61
+
62
+ self.pre_finish()
63
+ self.finish()
64
+ if save_data:
65
+ self.save_data()
66
+ self.post_finish()
67
+
68
+ self._running = True
69
+
70
+ def _loop(self):
71
+ for i in range(self._trace_count):
72
+ self._logger.debug('Get wave data: %s', i)
73
+ self.pre_do()
74
+ start = datetime.datetime.now()
75
+ self.do()
76
+ print('count: ', i, 'delay: ', datetime.datetime.now() - start)
77
+ trigger_judge_start_time = datetime.datetime.now().microsecond
78
+ # while self._running:
79
+ # trigger_judge_time = datetime.datetime.now().microsecond - trigger_judge_start_time
80
+ # if trigger_judge_time > self._trigger_judge_timeout:
81
+ # self._logger.error("Triggered judge timeout and will get next waves, "
82
+ # "judge time: %s and timeout is %s",
83
+ # trigger_judge_time, self._trigger_judge_timeout)
84
+ # break
85
+ # self._logger.debug('Judge trigger status.')
86
+ # # if self._is_triggered():
87
+ # # self._last_wave = self._get_waves()
88
+ # # if self._last_wave is not None:
89
+ # # self._logger.debug('Got wave: %s.', self._last_wave.shape)
90
+ # # if self._on_wave_loaded_callback and callable(self._on_wave_loaded_callback):
91
+ # # try:
92
+ # # self._on_wave_loaded_callback(self._last_wave)
93
+ # # except Exception as e:
94
+ # # self._logger.error('Wave loaded event callback error: %s', e.args)
95
+ # # time.sleep(1) # test
96
+ # # break
97
+ # break
98
+ # time.sleep(self._trigger_judge_wait_time)
99
+ self._save_wave()
100
+ self._post_do()
101
+
102
+ def _loop_without_log(self):
103
+ for i in range(self._trace_count):
104
+ # print('yes', self._logger.handlers[0].stream)
105
+ # self._logger.debug('Get wave data: %s', i)
106
+ self.pre_do()
107
+ self.do()
108
+ trigger_judge_start_time = datetime.datetime.now().microsecond
109
+ while self._running:
110
+ trigger_judge_time = datetime.datetime.now().microsecond - trigger_judge_start_time
111
+ if trigger_judge_time > self._trigger_judge_timeout:
112
+ # self._logger.error("Triggered judge timeout and will get next waves, "
113
+ # "judge time: %s and timeout is %s",
114
+ # trigger_judge_time, self._trigger_judge_timeout)
115
+ break
116
+ # self._logger.debug('Judge trigger status.')
117
+ if self._is_triggered():
118
+ self._last_wave = self._get_waves()
119
+ if self._last_wave is not None:
120
+ ...
121
+ # self._logger.debug('Got wave: %s.', self._last_wave.shape)
122
+ if self._on_wave_loaded_callback and callable(self._on_wave_loaded_callback):
123
+ try:
124
+ self._on_wave_loaded_callback(self._last_wave)
125
+ except Exception as e:
126
+ ...
127
+ # self._logger.error('Wave loaded event callback error: %s', e.args)
128
+ time.sleep(1)
129
+ break
130
+ time.sleep(self._trigger_judge_wait_time)
131
+ self._save_wave()
132
+ self._post_do()
133
+
134
+ def connect_scrat(self):
135
+ """
136
+ Connect to scrat device
137
+ :return:
138
+ """
139
+ ...
140
+
141
+ def connect_cracker(self):
142
+ """
143
+ Connect to cracker device.
144
+ :return:
145
+ """
146
+ self._cracker.connect()
147
+
148
+ def connect_net(self):
149
+ ...
150
+
151
+ def config_scrat(self):
152
+ ...
153
+
154
+ def config_cracker(self):
155
+ ...
156
+
157
+ def pre_init(self):
158
+ ...
159
+
160
+ def init(self):
161
+ ...
162
+
163
+
164
+ def post_init(self):
165
+ ...
166
+
167
+ def transfer(self):
168
+ ...
169
+
170
+ def pre_do(self):
171
+ ...
172
+
173
+ def do(self):
174
+ ...
175
+
176
+ def _post_do(self):
177
+ ...
178
+
179
+ def arm(self):
180
+ ...
181
+
182
+ def _is_triggered(self):
183
+ # for test
184
+ time.sleep(0.1)
185
+ return True
186
+
187
+ def _get_waves(self):
188
+ return np.array([np.random.random(1000)])
189
+
190
+ def _save_wave(self):
191
+ ...
192
+
193
+ def save_data(self, data_type: str = 'zarr'):
194
+ """
195
+ Save wave, key and other info to acquisition dataset file.
196
+ """
197
+ # if data_type == 'zarr':
198
+ # zarr.create()
199
+ ...
200
+
201
+ def pre_finish(self):
202
+ ...
203
+
204
+ def post_finish(self):
205
+ ...
206
+
207
+ def save_dataset(self):
208
+ ...
209
+
210
+ def finish(self):
211
+ pass
212
+
213
+ def get_last_wave(self):
214
+ return self._last_wave
File without changes
@@ -0,0 +1,355 @@
1
+ import socket
2
+ import struct
3
+ import typing
4
+ from abc import ABC
5
+ from abc import abstractmethod
6
+
7
+ from cracknuts import logger
8
+ from cracknuts.cracker import protocol
9
+ import cracknuts.utils.hex_util as hex_util
10
+
11
+
12
+ class Commands:
13
+ """
14
+ Protocol commands.
15
+ """
16
+ GET_ID = 0x0001
17
+ GET_NAME = 0x0002
18
+
19
+ SCRAT_ANALOG_CHANNEL_ENABLE = 0x0100
20
+ SCRAT_ANALOG_COUPLING = 0x0101
21
+ SCRAT_ANALOG_VOLTAGE = 0x0102
22
+ SCRAT_ANALOG_BIAS_VOLTAGE = 0x0103
23
+ SCRAT_ANALOG_GAIN = 0x0104
24
+
25
+ SCRAT_DIGITAL_CHANNEL_ENABLE = 0x0110
26
+ SCRAT_DIGITAL_VOLTAGE = 0x0111
27
+
28
+ SCRAT_TRIGGER_MODE = 0x0120
29
+
30
+ SCRAT_ANALOG_TRIGGER_SOURCE = 0x0121
31
+ SCRAT_DIGITAL_TRIGGER_SOURCE = 0x0122
32
+
33
+ SCRAT_ANALOG_TRIGGER_VOLTAGE = 0x0123
34
+
35
+ SCRAT_TRIGGER_DELAY = 0x0124
36
+
37
+ SCRAT_SAMPLE_LENGTH = 0x0125
38
+
39
+ SCRAT_ARM = 0x0126
40
+
41
+ SCRAT_IS_TRIGGERED = 0x0127
42
+
43
+ SCRAT_GET_ANALOG_WAVES = 0x0130
44
+ SCRAT_GET_DIGITAL_WAVES = 0x0130
45
+
46
+ CRACKER_NUT_ENABLE = 0x0200
47
+ CRACKER_NUT_VOLTAGE = 0x0201
48
+ CRACKER_NUT_INTERFACE = 0x0210
49
+ CRACKER_NUT_TIMEOUT = 0x0224
50
+
51
+ CRACKER_SERIAL_BAUD = 0x0220
52
+ CRACKER_SERIAL_WIDTH = 0x0221
53
+ CRACKER_SERIAL_STOP = 0x0222
54
+ CRACKER_SERIAL_ODD_EVE = 0x0223
55
+ CRACKER_SERIAL_DATA = 0x022A
56
+
57
+ CRACKER_SPI_CPOL = 0x0230
58
+ CRACKER_SPI_CPHA = 0x0231
59
+ CRACKER_SPI_DATA_LEN = 0x0232
60
+ CRACKER_SPI_FREQ = 0x0233
61
+ CRACKER_SPI_TIMEOUT = 0x0234
62
+ CRACKER_SPI_DATA = 0x023A
63
+
64
+ CRACKER_I2C_FREQ = 0x0240
65
+ CRACKER_I2C_TIMEOUT = 0x0244
66
+ CRACKER_I2C_DATA = 0x024A
67
+
68
+ CRACKER_CAN_FREQ = 0x0250
69
+ CRACKER_CAN_TIMEOUT = 0x0254
70
+ CRACKER_CA_DATA = 0x025A
71
+
72
+
73
+ class AbsCracker(ABC):
74
+ """Cracker
75
+ Cracker
76
+ """
77
+
78
+ def __init__(self, server_address=None):
79
+ """
80
+ :param server_address: Cracker device address (ip, port)
81
+ """
82
+ self._logger = logger.get_logger(self)
83
+ self._server_address = server_address
84
+ self._socket: socket.socket | None = None
85
+ self._connection_status = False
86
+
87
+ def set_addr(self, ip, port) -> None:
88
+ self._server_address = ip, port
89
+
90
+ def connect(self):
91
+ """
92
+ Connect to Cracker device.
93
+ :return: Cracker self.
94
+ """
95
+ try:
96
+ if not self._socket:
97
+ self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
98
+ self._socket.settimeout(5)
99
+ self._socket.connect(self._server_address)
100
+ self._connection_status = True
101
+ self._logger.info('Connected to cracker: {}'.format(self._server_address))
102
+ except socket.error as e:
103
+ self._logger.error('Connection failed: %s', e)
104
+ self._connection_status = False
105
+ return self
106
+
107
+ def disconnect(self):
108
+ """
109
+ Disconnect Cracker device.
110
+ :return: Cracker self.
111
+ """
112
+ try:
113
+ if self._socket:
114
+ self._socket.close()
115
+ self._socket = None
116
+ self._logger.info(f'Disconnect from {self._server_address}')
117
+ except socket.error as e:
118
+ self._logger.error('Disconnection failed: %s', e)
119
+ finally:
120
+ self._connection_status = False
121
+ return self
122
+
123
+ def reconnect(self):
124
+ """
125
+ Reconnect to Cracker device.
126
+ :return: Cracker self.
127
+ """
128
+ self.disconnect()
129
+ self.connect()
130
+
131
+ def get_connection_status(self):
132
+ """
133
+ Get connection status.
134
+ :return: True or False
135
+ """
136
+ return self._connection_status
137
+
138
+ def send_and_receive(self, message) -> None | bytes:
139
+ """
140
+ Send message to socket
141
+ :param message:
142
+ :return:
143
+ """
144
+ try:
145
+ if not self.get_connection_status():
146
+ self.connect()
147
+ self._logger.debug("Send message to %s: \n%s", self._server_address,
148
+ hex_util.get_bytes_matrix(message))
149
+ self._socket.sendall(message)
150
+ resp_header = self._socket.recv(protocol.RESP_HEADER_SIZE)
151
+ self._logger.debug("Get response header from %s: \n%s", self._server_address,
152
+ hex_util.get_bytes_matrix(resp_header))
153
+ magic, version, direction, status, length = struct.unpack(
154
+ protocol.RESP_HEADER_FORMAT, resp_header
155
+ )
156
+ self._logger.debug(
157
+ "Receive header from %s: %s",
158
+ self._server_address,
159
+ (magic, version, direction, status, length),
160
+ )
161
+
162
+ if length == 0:
163
+ return None
164
+ resp_payload = self._socket.recv(length)
165
+ self._logger.debug(
166
+ "Receive payload from %s: \n%s", self._server_address, hex_util.get_bytes_matrix(resp_payload)
167
+ )
168
+ return resp_payload
169
+ except socket.error as e:
170
+ self._logger.error('Send message failed: %s', e)
171
+ return None
172
+
173
+ def send_with_command(self, command: int | bytes, payload: str | bytes = None):
174
+ if isinstance(payload, str):
175
+ payload = bytes.fromhex(payload)
176
+ return self.send_and_receive(protocol.build_send_message(command, payload))
177
+
178
+ def echo(self, payload: str) -> str:
179
+ """
180
+ length <= 1024
181
+ """
182
+ self._socket.sendall(payload.encode('ascii'))
183
+ res = self._socket.recv(1024).decode('ascii')
184
+ self._logger.debug(f'Get response: {res}')
185
+ return res
186
+
187
+ def echo_hex(self, payload: str) -> str:
188
+ """
189
+ length <= 1024
190
+ """
191
+ payload = bytes.fromhex(payload)
192
+ self._socket.sendall(payload)
193
+ res = self._socket.recv(1024).hex()
194
+ self._logger.debug(f'Get response: {res}')
195
+ return res
196
+
197
+ @abstractmethod
198
+ def get_id(self) -> str:
199
+ ...
200
+
201
+ @abstractmethod
202
+ def get_name(self) -> str:
203
+ ...
204
+
205
+ @abstractmethod
206
+ def scrat_analog_channel_enable(self, enable: typing.Dict[int, bool]):
207
+ ...
208
+
209
+ @abstractmethod
210
+ def scrat_analog_coupling(self, coupling: typing.Dict[int, int]):
211
+ ...
212
+
213
+ @abstractmethod
214
+ def scrat_analog_voltage(self, channel: int, voltage: int):
215
+ ...
216
+
217
+ @abstractmethod
218
+ def scrat_analog_bias_voltage(self, channel: int, voltage: int):
219
+ ...
220
+
221
+ @abstractmethod
222
+ def scrat_digital_channel_enable(self, enable: typing.Dict[int, bool]):
223
+ ...
224
+
225
+ @abstractmethod
226
+ def scrat_digital_voltage(self, voltage: int):
227
+ ...
228
+
229
+ @abstractmethod
230
+ def scrat_trigger_mode(self, source: int, stop: int):
231
+ ...
232
+
233
+ @abstractmethod
234
+ def scrat_analog_trigger_source(self, channel: int):
235
+ ...
236
+
237
+ @abstractmethod
238
+ def scrat_digital_trigger_source(self, channel: int):
239
+ ...
240
+
241
+ @abstractmethod
242
+ def scrat_analog_trigger_voltage(self, voltage: int):
243
+ ...
244
+
245
+ @abstractmethod
246
+ def scrat_trigger_delay(self, delay: int):
247
+ ...
248
+
249
+ @abstractmethod
250
+ def scrat_sample_len(self, length: int):
251
+ ...
252
+
253
+ @abstractmethod
254
+ def scrat_arm(self):
255
+ ...
256
+
257
+ @abstractmethod
258
+ def scrat_is_triggered(self):
259
+ ...
260
+
261
+ @abstractmethod
262
+ def scrat_get_analog_wave(self, channel: int, offset: int, sample_count: int):
263
+ ...
264
+
265
+ @abstractmethod
266
+ def scrat_get_digital_wave(self, channel: int, offset: int, sample_count: int):
267
+ ...
268
+
269
+ @abstractmethod
270
+ def scrat_analog_gain(self, gain: int):
271
+ ...
272
+
273
+ @abstractmethod
274
+ def cracker_nut_enable(self, enable: int):
275
+ ...
276
+
277
+ @abstractmethod
278
+ def cracker_nut_voltage(self, voltage: int):
279
+ ...
280
+
281
+ @abstractmethod
282
+ def cracker_nut_interface(self, interface: typing.Dict[int, bool]):
283
+ ...
284
+
285
+ @abstractmethod
286
+ def cracker_nut_timeout(self, timeout: int):
287
+ ...
288
+
289
+ @abstractmethod
290
+ def cracker_serial_baud(self, baud: int):
291
+ ...
292
+
293
+ @abstractmethod
294
+ def cracker_serial_width(self, width: int):
295
+ ...
296
+
297
+ @abstractmethod
298
+ def cracker_serial_stop(self, stop: int):
299
+ ...
300
+
301
+ @abstractmethod
302
+ def cracker_serial_odd_eve(self, odd_eve: int):
303
+ ...
304
+
305
+ @abstractmethod
306
+ def cracker_serial_data(self, expect_len: int, data: bytes):
307
+ ...
308
+
309
+ @abstractmethod
310
+ def cracker_spi_cpol(self, cpol: int):
311
+ ...
312
+
313
+ @abstractmethod
314
+ def cracker_spi_cpha(self, cpha: int):
315
+ ...
316
+
317
+ @abstractmethod
318
+ def cracker_spi_data_len(self, cpha: int):
319
+ ...
320
+
321
+ @abstractmethod
322
+ def cracker_spi_freq(self, freq: int):
323
+ ...
324
+
325
+ @abstractmethod
326
+ def cracker_spi_timeout(self, timeout: int):
327
+ ...
328
+
329
+ @abstractmethod
330
+ def cracker_spi_data(self, expect_len: int, data: bytes):
331
+ ...
332
+
333
+ @abstractmethod
334
+ def cracker_i2c_freq(self, freq: int):
335
+ ...
336
+
337
+ @abstractmethod
338
+ def cracker_i2c_timeout(self, timeout: int):
339
+ ...
340
+
341
+ @abstractmethod
342
+ def cracker_i2c_data(self, expect_len: int, data: bytes):
343
+ ...
344
+
345
+ @abstractmethod
346
+ def cracker_can_freq(self, freq: int):
347
+ ...
348
+
349
+ @abstractmethod
350
+ def cracker_can_timeout(self, timeout: int):
351
+ ...
352
+
353
+ @abstractmethod
354
+ def cracker_can_data(self, expect_len: int, data: bytes):
355
+ ...