flandre/flandre/utils/RfMeta.py
flandre b6fa30fb42 del json
add qt watermark
2025-04-13 17:24:19 +08:00

148 lines
3.8 KiB
Python

import dataclasses
import json
from dataclasses import dataclass
from enum import Enum, auto
from pathlib import Path
from typing import Annotated, get_type_hints
# from attr import dataclass
COMMIT_KEY = 'COMMIT'
class RfMeta:
@classmethod
def p2a(clz):
gh = get_type_hints(clz, include_extras=True)
return {k: gh[k].__metadata__[0] for k in gh}
@classmethod
def p2t(clz):
return get_type_hints(clz)
@classmethod
def a2p(clz):
return {v: k for k, v in clz.p2a().items()}
@property
def name(self):
p2a = self.p2a()
p2t = self.p2t()
a2p = self.a2p()
arr = []
if COMMIT_KEY in a2p:
cp = a2p[COMMIT_KEY]
del p2a[cp]
arr.append(f'{self.__getattribute__(cp)}')
for p in p2a:
t = p2t[p]
v = self.__getattribute__(p)
if issubclass(t, Enum):
vs = v.name
elif issubclass(t, tuple):
vs = f'({' '.join([str(vv) for vv in v])})'
else:
vs = str(v)
if v is not None:
arr.append(f'{p2a[p]}={vs}')
return ",".join(arr)
@property
def filename(self):
return self.name + '.bin'
@classmethod
def from_path(clz, path: Path | str):
path = Path(path)
if not path.exists():
raise FileNotFoundError(path)
if path.is_file():
return clz.from_name(path.stem)
elif path.is_dir():
return clz.from_name(path.name)
else:
raise FileNotFoundError
@classmethod
def from_name(clz, name: str):
if Path(name).suffix == '.zip':
name = Path(name).stem
p2t = clz.p2t()
a2p = clz.a2p()
c = clz()
sp = name.split(',')
if COMMIT_KEY in a2p:
c.__setattr__(a2p[COMMIT_KEY], sp.pop(0))
for pv in sp:
a, v = pv.split('=')
p = a2p[a]
t = p2t[p]
if issubclass(t, Enum):
c.__setattr__(p, t[v])
elif issubclass(t, tuple):
c.__setattr__(p, tuple(int(i) for i in v[1:-1].split(' ')))
else:
c.__setattr__(p, t(v))
return c
@dataclass
class RfFrameMeta(RfMeta):
encoder: Annotated[int, 'E'] = None
sequence_id: Annotated[int, 'S'] = None # test3
robot_x: Annotated[int, 'X'] = None
robot_y: Annotated[int, 'Y'] = None
robot_z: Annotated[int, 'Z'] = None
robot_roll: Annotated[int, 'RX'] = None
robot_pitch: Annotated[int, 'RY'] = None
robot_yal: Annotated[int, 'RZ'] = None
robot_force_x: Annotated[int, 'FX'] = None
robot_force_y: Annotated[int, 'FY'] = None
robot_force_z: Annotated[int, 'FZ'] = None
robot_force_roll: Annotated[int, 'FRX'] = None
robot_force_pitch: Annotated[int, 'FRY'] = None
robot_force_yal: Annotated[int, 'FRZ'] = None
blake2b: Annotated[str, 'B2B'] = None
@dataclass
class RfSequenceMeta(RfMeta):
class RfSequenceMode(Enum):
PWI = auto()
TFM = auto()
commit: Annotated[str, COMMIT_KEY] = None
shape: Annotated[tuple, 'S'] = None
mode: Annotated[RfSequenceMode, 'M'] = RfSequenceMode.PWI
us: Annotated[int, 'U'] = None
def prod(self):
res = 1
for i in self.shape:
res *= int(i)
return res
def d(self):
return self.shape.__len__()
if __name__ == '__main__':
# r = RfSequenceMeta.from_name('asdasd1,S=(64 1501),M=PWI,U=30')
# print(r)
# print(r.json_str)
#
# r2 = RfSequenceMeta.from_json_str(r.json_str)
# print(r2)
r = RfFrameMeta.from_name('E=1,S=123')
print(r)
print(r.json_str)
r2 = RfFrameMeta.from_json_str(r.json_str)
print(r2)