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% |