Joint-python-library 0.0.6__tar.gz → 0.0.7__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.
Files changed (20) hide show
  1. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/PKG-INFO +1 -1
  2. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/PKG-INFO +1 -1
  3. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/Slave_Device.py +109 -1
  4. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/joint.py +110 -1
  5. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/setup.py +1 -1
  6. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/SOURCES.txt +0 -0
  7. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/dependency_links.txt +0 -0
  8. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/entry_points.txt +0 -0
  9. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/requires.txt +0 -0
  10. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/Joint_python_library.egg-info/top_level.txt +0 -0
  11. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/LICENSE +0 -0
  12. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/README.md +0 -0
  13. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/__init__.py +0 -0
  14. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/acrome_joint/serial_port.py +0 -0
  15. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/__init__.py +0 -0
  16. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/joint_device.py +0 -0
  17. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/limits.py +0 -0
  18. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/main.py +0 -0
  19. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/gui/ramp_trajectory.py +0 -0
  20. {joint_python_library-0.0.6 → joint_python_library-0.0.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Joint-python-library
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: Python library for interfacing with Acrome Robotic Arm Joint BLDC Motor Controllers. This Python library provides an easy-to-use interface for communication and control of BLDC motor controllers used in Acrome robotic arm joints. It is designed to simplify the integration of Acrome’s robotic joint actuators into custom applications, allowing developers and researchers to focus on building advanced robotic systems without dealing with low-level communication details.
5
5
  Home-page: https://github.com/Acrome-Smart-Motion-Devices/python-library-new
6
6
  Author: BeratComputer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Joint-python-library
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: Python library for interfacing with Acrome Robotic Arm Joint BLDC Motor Controllers. This Python library provides an easy-to-use interface for communication and control of BLDC motor controllers used in Acrome robotic arm joints. It is designed to simplify the integration of Acrome’s robotic joint actuators into custom applications, allowing developers and researchers to focus on building advanced robotic systems without dealing with low-level communication details.
5
5
  Home-page: https://github.com/Acrome-Smart-Motion-Devices/python-library-new
6
6
  Author: BeratComputer
@@ -10,6 +10,7 @@ HEADER, ID, DEVICE_FAMILY, PACKAGE_SIZE, COMMAND, STATUS, .............. DATA ..
10
10
  '''
11
11
 
12
12
  PING_PACKAGE_SIZE = 10
13
+ BROADCAST_ID = 255
13
14
 
14
15
  #Classical Device Indexes
15
16
  Index_Device_Classical = enum.IntEnum('Index', [
@@ -86,7 +87,9 @@ class Slave_Device():
86
87
  SERIAL_HEADER = 0x55
87
88
  _BROADCAST_ID = 0xFF
88
89
 
89
- _BATCH_ID = 254
90
+ # NEW: device_family → variables (Data_ list) kaydı
91
+ _vars_registry = {} # { device_family:int : [Data_, Data_, ...] }
92
+
90
93
  def __init__(self, id, device_family, variables, port:SerialPort):
91
94
  self._port = port
92
95
  self._header = self.SERIAL_HEADER
@@ -97,6 +100,7 @@ class Slave_Device():
97
100
  self.__post_sleep = 0.01
98
101
  self.__device_init_sleep = 3
99
102
  self.write_ack_enable = False
103
+ Slave_Device._vars_registry.setdefault(device_family, variables)
100
104
 
101
105
  def enable_get_ack(self):
102
106
  self.write_ack_enable = True
@@ -312,3 +316,107 @@ class Data_():
312
316
 
313
317
  def type(self) -> str:
314
318
  return self.__type
319
+
320
+
321
+
322
+ def write_sync_to_many(
323
+ port: SerialPort,
324
+ device_family: int,
325
+ index: int,
326
+ *id_value_pairs,
327
+ expect_ack: bool = False
328
+ ) -> bool:
329
+ """
330
+ Aynı değişken index'ini birden fazla cihaza WRITE_SYNC ile yazar.
331
+ Değer tipi, device_family'nin kayıtlı değişken tablosundan otomatik çekilir.
332
+
333
+ Args:
334
+ port (SerialPort): paylaşılan seri port
335
+ device_family (int): ürün ailesi (ör. Joint için 0xDA)
336
+ index (int | enum.IntEnum): yazılacak değişken indeksi
337
+ *id_value_pairs: [id, value] çiftleri (list/tuple), örn: [0, 123], [1, -45], ...
338
+ expect_ack (bool): ACK beklenip beklenmeyeceği
339
+
340
+ Returns:
341
+ bool: True = yazdı (veya ACK doğrulandı); False = ACK bekleniyorsa doğrulanamadı
342
+ """
343
+ import struct
344
+ from crccheck.crc import Crc32Mpeg2 as CRC32
345
+
346
+ # Sabitler
347
+ HEADER = Slave_Device.SERIAL_HEADER
348
+ BATCH_ID = Slave_Device._BROADCAST_ID
349
+ PING_PACKAGE_SIZE = 10
350
+ WRITE_SYNC = int(Device_Commands.WRITE_SYNC)
351
+ STATUS = 0
352
+
353
+ # Registry ve tip çözümü
354
+ reg = Slave_Device._vars_registry.get(device_family)
355
+ if reg is None:
356
+ raise RuntimeError(
357
+ f"Device family 0x{device_family:02X} için değişken tablosu bulunamadı. "
358
+ "Bu family’den en az bir cihaz instance'ı oluşturulmuş olmalı."
359
+ )
360
+
361
+ idx_int = int(index)
362
+ try:
363
+ var_type = reg[idx_int].type() # 'f', 'i', 'B', ...
364
+ except Exception as e:
365
+ raise ValueError(f"Geçersiz index: {index} (family=0x{device_family:02X}).") from e
366
+
367
+ # id_value_pairs doğrula ve düzle
368
+ flat = []
369
+ for pair in id_value_pairs:
370
+ if (not isinstance(pair, (list, tuple))) or len(pair) != 2:
371
+ raise ValueError(f"{pair} geçersiz. [ID, value] olmalı.")
372
+ dev_id, val = pair
373
+ if not (0 <= int(dev_id) <= 254):
374
+ raise ValueError(f"ID {dev_id} geçersiz (0..254).")
375
+ # 'val' tipi Data_.type() ile belirlenecek; pack sırasında kontrol olur
376
+ flat.extend([int(dev_id), val])
377
+
378
+ count = len(flat) // 2
379
+ if count == 0:
380
+ raise ValueError("En az bir [ID, value] çifti gerekli.")
381
+
382
+ val_size = struct.calcsize('<' + var_type)
383
+
384
+ # Paket boyutu
385
+ # payload = index(1B) + her cihaz için (ID:1B + value:val_size)
386
+ payload_size = 1 + count * (1 + val_size)
387
+ package_size = PING_PACKAGE_SIZE + payload_size
388
+
389
+ # Format: header, BATCH_ID, family, size, cmd, status, index, (id, value)*N, crc
390
+ fmt = '<BBBBBB' + 'B' + ('B' + var_type) * count
391
+ data_no_crc = struct.pack(
392
+ fmt,
393
+ HEADER,
394
+ BATCH_ID,
395
+ device_family,
396
+ package_size,
397
+ WRITE_SYNC,
398
+ STATUS,
399
+ idx_int,
400
+ *flat
401
+ )
402
+ pkt = data_no_crc + struct.pack('<I', CRC32.calc(data_no_crc))
403
+
404
+ # Gönder
405
+ port._write_bus(pkt)
406
+
407
+ if not expect_ack:
408
+ return True
409
+
410
+ # Basit ACK okuma (PING_PACKAGE_SIZE kadar)
411
+ ack = port._read_bus(size=PING_PACKAGE_SIZE)
412
+ if not ack or len(ack) != PING_PACKAGE_SIZE:
413
+ return False
414
+
415
+ # CRC kontrolü
416
+ try:
417
+ data_part = ack[:-4]
418
+ crc_part = ack[-4:]
419
+ ok = (CRC32.calc(data_part) == struct.unpack('<I', crc_part)[0])
420
+ return bool(ok)
421
+ except Exception:
422
+ return False
@@ -323,4 +323,113 @@ class Joint(Slave_Device):
323
323
 
324
324
  elif package_number == 3:
325
325
  return self.get_variables(*classic_package)
326
-
326
+
327
+
328
+
329
+ def set_joint_variables_sync(port:SerialPort, parameter_idx, *idx_val_pairs):
330
+ """
331
+ Build & send a WRITE_SYNC packet:
332
+ [HEADER, 0xFF, DEVICE_FAMILY, LENGTH, WRITE_SYNC, 0, PARAM_IDX, (ID, VALUE)*, CRC32]
333
+ - parameter_idx: single parameter index to write on each target
334
+ - idx_val_pairs: variadic list of 2-tuples/lists like (id, value) or [id, value]
335
+ - port: SerialPort-like object that has write(bytes) method
336
+
337
+ Returns: number of bytes written.
338
+ Raises: ValueError on malformed inputs.
339
+ """
340
+
341
+ # --- Validate & fetch parameter meta
342
+ if parameter_idx not in VARS:
343
+ raise ValueError(f"Unknown parameter index: {parameter_idx}")
344
+
345
+ var_desc = VARS[parameter_idx]
346
+ val_fmt = var_desc.type() # e.g., 'f', 'i', 'H', etc. (little-endian will be applied later)
347
+ val_size = var_desc.size() # size in bytes
348
+
349
+ # --- Validate pairs; normalize to tuples
350
+ pairs = []
351
+ for p in idx_val_pairs:
352
+ if not hasattr(p, '__len__') or len(p) != 2:
353
+ raise ValueError(f"{p} must be a pair like [ID, value]")
354
+ dev_id, value = p[0], p[1]
355
+
356
+ # Device ID range (0..254), 255 is reserved for broadcast in header
357
+ if not (0 <= int(dev_id) <= 254):
358
+ raise ValueError(f"Device ID out of range (0..254): {dev_id}")
359
+
360
+ pairs.append((int(dev_id), value))
361
+
362
+ if not pairs:
363
+ raise ValueError("At least one [ID, value] pair is required.")
364
+
365
+ # --- Compute size field used by your protocol
366
+ # Payload after the 6 fixed header bytes:
367
+ # PARAM_IDX (1 byte)
368
+ # + for each pair: ID (1 byte) + VALUE (val_size bytes)
369
+ payload_size = 1 + len(pairs) * (1 + val_size)
370
+
371
+ # Protocol total-length field used in your other function:
372
+ # size + PING_PACKAGE_SIZE (to mirror your existing framing)
373
+ length_field = payload_size + PING_PACKAGE_SIZE
374
+
375
+ # --- Build struct format string & flat args
376
+ # Fixed header: '<BBBBBB'
377
+ # Then: PARAM_IDX (B)
378
+ # Then for each pair: ID (B) + VALUE (val_fmt)
379
+ fmt = '<BBBBBB' + 'B' + ''.join(['B' + val_fmt for _ in pairs])
380
+
381
+ flat = [
382
+ dev.SERIAL_HEADER, # header
383
+ 0xFF, # broadcast ID
384
+ DEVICE_FAMILY, # device family
385
+ length_field, # total length field
386
+ Device_Commands.WRITE_SYNC, # command
387
+ 0x00, # reserved
388
+ int(parameter_idx), # parameter index
389
+ ]
390
+
391
+ # Append all (ID, VALUE) flattened; VALUE goes in native python type, struct packs it
392
+ for dev_id, value in pairs:
393
+ flat.append(dev_id)
394
+ flat.append(value)
395
+
396
+ # --- Pack without CRC
397
+ pkt_wo_crc = struct.pack(fmt, *flat)
398
+
399
+ # --- Append CRC32 (little-endian uint32 of the bytes above)
400
+ pkt = pkt_wo_crc + struct.pack('<I', CRC32.calc(pkt_wo_crc))
401
+
402
+ # --- Send over the provided port (broadcast sync write typically has no ACK)
403
+ written = port.write(pkt)
404
+ return written
405
+
406
+
407
+ def set_variables(self, *idx_val_pairs, ack = False):
408
+ # returns : did ACK come?
409
+ fmt_str = '<BBBBBB'
410
+ var_count = 0
411
+ size = 0
412
+ for one_pair in idx_val_pairs:
413
+ try:
414
+ if len(one_pair) != 2:
415
+ raise ValueError(f"{one_pair} more than a pair! It is not a pair")
416
+ else:
417
+ fmt_str += ('B' + self._vars[one_pair[0]].type())
418
+ var_count+=1
419
+ size += (1 + self._vars[one_pair[0]].size())
420
+ except:
421
+ raise ValueError(f"{one_pair} is not proper pair")
422
+
423
+ flattened_list = [item for sublist in idx_val_pairs for item in sublist]
424
+
425
+ struct_out = list(struct.pack(fmt_str, *[self._header, self._id, self._device_family, size + PING_PACKAGE_SIZE, Device_Commands.WRITE, 0, *flattened_list]))
426
+ struct_out = bytes(struct_out) + struct.pack('<' + 'I', CRC32.calc(struct_out))
427
+ self._ack_size = PING_PACKAGE_SIZE
428
+
429
+ self._write_port(struct_out)
430
+ if(self.write_ack_enable):
431
+ if self._read_ack():
432
+ return True
433
+ else:
434
+ return False
435
+ return False
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="Joint-python-library",
8
- version="0.0.6",
8
+ version="0.0.7",
9
9
  author="BeratComputer",
10
10
  author_email="beratdogan@acrome.net",
11
11
  description="Python library for interfacing with Acrome Robotic Arm Joint BLDC Motor Controllers. This Python library provides an easy-to-use interface for communication and control of BLDC motor controllers used in Acrome robotic arm joints. It is designed to simplify the integration of Acrome’s robotic joint actuators into custom applications, allowing developers and researchers to focus on building advanced robotic systems without dealing with low-level communication details.",