Diskussion:Nova 35: Unterschied zwischen den Versionen
Aus FabLab Region Nürnberg
Mose (Diskussion | Beiträge) |
Mose (Diskussion | Beiträge) |
||
Zeile 21: | Zeile 21: | ||
=== rdcam.py === | === rdcam.py === | ||
< | <pre> | ||
def send_command(payload): | |||
</ | data=scramble_bytes(payload) | ||
checksum=sum(data) | |||
b1=checksum&0xff | |||
b0=(checksum>>8)&0xff | |||
return bytes([b0,b1])+data | |||
def encode_number(n,l=5): | |||
res=[] | |||
while n>0: | |||
res.append(n&0x7f) | |||
n>>=7 | |||
while len(res)<l: | |||
res.append(0) | |||
res.reverse() | |||
return bytes(res) | |||
def decode_number(x): | |||
fak=1 | |||
res=0 | |||
for b in reversed(x): | |||
res+=fak*b | |||
fak*=0x80 | |||
return res | |||
def format_capture(c): | |||
for p in c: | |||
direction=p["_source"]['layers']['udp']['udp.port']=='50200' | |||
data=unscramble_packet(p,checksum=direction) | |||
line='-> ' if direction else '<- ' | |||
line+=' '.join([bytes(x).hex() for x in split_messages(data)]) | |||
print(line) | |||
def split_messages(d): | |||
m=[] | |||
res=[m] | |||
for x in d: | |||
if x&0x80: | |||
m=[] | |||
res.append(m) | |||
m.append(x) | |||
return res | |||
def unscramble_packet(p,checksum=False): | |||
string=p["_source"]["layers"]["data"]["data.data_raw"] | |||
if checksum: | |||
return list(bytes.fromhex(string[:4]))+unscramble_string(string[4:]) | |||
else: | |||
return unscramble_string(string) | |||
def unscramble_string(s): | |||
return [unscramble(b) for b in bytes.fromhex(s)] | |||
def unscramble(b): | |||
res_b=b-1 | |||
if res_b<0: res_b+=0x100 | |||
res_b^=0x88 | |||
fb=res_b&0x80 | |||
lb=res_b&1 | |||
res_b=res_b-fb-lb | |||
res_b|=lb<<7 | |||
res_b|=fb>>7 | |||
return res_b | |||
def scramble(b): | |||
fb=b&0x80 | |||
lb=b&1 | |||
res_b=b-fb-lb | |||
res_b|=lb<<7 | |||
res_b|=fb>>7 | |||
res_b^=0x88 | |||
res_b+=1 | |||
if res_b>0xff:res_b-=0x100 | |||
return res_b | |||
def scramble_bytes(bs): | |||
return bytes([scramble(b) for b in bs]) | |||
def unscramble_bytes(bs): | |||
return bytes([unscramble(b) for b in bs]) | |||
</pre> | |||
=== Data format === | === Data format === |
Version vom 21. Mai 2017, 01:31 Uhr
Hardware
- RDC6442G Herstellerseite
- Network aware laser cutter security
- RDCAM Reverse Engineering
- RDworks + Manuals
Protokollanalyse
- Capture mit Wireshark
- Datei > Paketdissektion exportieren > Als JSON
- Packet summary line
- Include column headings
- Packet details:
- As displayed
- Packet Bytes
- Packet summary line
- some more pat foo
rdcam.py
def send_command(payload): data=scramble_bytes(payload) checksum=sum(data) b1=checksum&0xff b0=(checksum>>8)&0xff return bytes([b0,b1])+data def encode_number(n,l=5): res=[] while n>0: res.append(n&0x7f) n>>=7 while len(res)<l: res.append(0) res.reverse() return bytes(res) def decode_number(x): fak=1 res=0 for b in reversed(x): res+=fak*b fak*=0x80 return res def format_capture(c): for p in c: direction=p["_source"]['layers']['udp']['udp.port']=='50200' data=unscramble_packet(p,checksum=direction) line='-> ' if direction else '<- ' line+=' '.join([bytes(x).hex() for x in split_messages(data)]) print(line) def split_messages(d): m=[] res=[m] for x in d: if x&0x80: m=[] res.append(m) m.append(x) return res def unscramble_packet(p,checksum=False): string=p["_source"]["layers"]["data"]["data.data_raw"] if checksum: return list(bytes.fromhex(string[:4]))+unscramble_string(string[4:]) else: return unscramble_string(string) def unscramble_string(s): return [unscramble(b) for b in bytes.fromhex(s)] def unscramble(b): res_b=b-1 if res_b<0: res_b+=0x100 res_b^=0x88 fb=res_b&0x80 lb=res_b&1 res_b=res_b-fb-lb res_b|=lb<<7 res_b|=fb>>7 return res_b def scramble(b): fb=b&0x80 lb=b&1 res_b=b-fb-lb res_b|=lb<<7 res_b|=fb>>7 res_b^=0x88 res_b+=1 if res_b>0xff:res_b-=0x100 return res_b def scramble_bytes(bs): return bytes([scramble(b) for b in bs]) def unscramble_bytes(bs): return bytes([unscramble(b) for b in bs])
Data format
- Byte = 1 Bit Message Start Indicator + 7 Bit Payload
- Only one message (checksum + command) can be sent per UDP package
- Max UDP package size 1472 bytes including checksum; fragmented by simple cutting (even inside a command)
Checksum
2 Bytes - sum of scrambled message bytes; MSB first.
Checksum has to be send before message.
Values
Value | Lenght | Description |
---|---|---|
ABSCOORD | 5 Bytes | absolute position relative to job origin in µm |
RELCOORD | 2 Bytes | relative position in µm; signed (2s complement) |
SPEED | 5 Bytes | speed in µm/s |
POWER | 2 Bytes | power in 0,006103516% (100/2^14) |
CSTRING | variable zero terminated |
Commands
Byte squence | Description | how sure we are |
---|---|---|
C6 01 <POWER> | 1st laser source min power | 99% |
C6 21 <POWER> | 2nd laser source min power | 99% |
C6 02 <POWER> | 1st laser source max power | 99% |
C6 22 <POWER> | 2nd laser source max power | 99% |
C9 02 <SPEED> | movement and/or (not sure) cutting speed | 80% |
D9 00 02 <ABSCOORD> | move X | 99% |
D9 00 03 <ABSCOORD> | move Y | 50% |
D9 00 04 <ABSCOORD> | move Z | 50% |
D9 00 05 <ABSCOORD> | move U | 50% |
CC | ACK from machine | 99% |
CD | ERR from machine | 99% |
DA 00 XX XX | get XX XX from machine | 99% |
DA 00 04 05 | saved job count | 99% |
DA 01 XX XX <VALUE> | response to DA 00 XX XX | 99% |
A8 <ABSCOORD> <ABSCOORD> | Straight cut to absolute X Y; turn laser on with configured speed and power | 99% |
A9 <RELCOORD> <RELCOORD> | Straight cut to relative X Y; turn laser on with configured speed and power | 99% |
E7 50 <ABSCOORD> <ABSCOORD> | Bounding box top left? | 30% |
E7 51 <ABSCOORD> <ABSCOORD> | Bounding box bottom right? | 30% |
E8 02 E7 01 <CSTRING> | Set filename for following transfer (transfer needs to be done really quickly after this!) | 90% |
E8 01 XX XX | Read filename number XX XX | |
88 <ABSCOORD> <ABSCOORD> | straight move to absolute X Y as fast as possible; with laser off | 99% |
89 <RELCOORD> <RELCOORD> | straight move to relative X Y as fast as possible; with laser off | 80% |