DA 00 XX XX - get XX XX from machine
I dream make my own hardware compatible with RDWorks. Reading RD-file from SD-card is not a problem. But communication with RDWorks software is a problem. I noticed that I should response in the following way DA 01 XX XX <VALUE>. For example, when I press any button in RDWorks it's first send DA 00 05 7E. But I don't found information about this commands, anyone has decoded this?
It's mentioned in Roger Clark's work: http://www.rogerclark.net/network-aware-laser-cutter-security/
e.g. This seems to be the initial packet that is always sent by RDWorks 02:61:d4:89:0d:f7 to which the RDC6442G responds with c6 and then sends a reply packet e.g. d4:09:0d:f7:8f:a1:09:c3:89
Which suggests the right response is:
swizzled is: b'\xd4\x09\x0d\xf7\x8f\xa1\x09\xc3\x89'
And unswizzled:
b'\xDA\x01' + bytearray(array[2:4]) + b'\x06\x28\x01\x4a\x00'
The issue I'm having is that this it's not enough to trick RDWorks.
I added a basic RuidaServer to MeerK40t ( https://github.com/meerk40t/meerk40t/commit/f98bd1ae088865f32e6e4b1c6a045c0d2aca907c ). The idea being I can tell MeerK40t to open that port, pretend to be a RuidaServer then control my M2 Nano with RDWorks for whatever reason you'd have for doing that. But, RDWorks says that that answer is wrong, quickly shutting down with "connection error". @jnweiger can you post a full exchange of the the devices babbling through a ruidaproxy? At least enough to figure out this handshake.
Figured it out. The required reply is certainly 0x65006500 for 0x05 0x7E. Most of the rest of the values you can just return 0.
634XG uses 0x11 xor as the swizzle. But all of them fail at: --> da000004 <-- da0100040000000000
Responding that 00 04 is equal to zero causes the program to terminate the connection. Goes through with 644XG, where it accepts 0 for that value. I have meerk40ts new version fully pretending to be a ruida device.
@ghost I've decoded all the commands. Literally 100% of them. That command actually is Get Parameter "Card ID". Also decoded all the parameters, some of them I can't even get RDWorks to bother asking for. Most of them even weird ones just dutifully get put into the boxes. I told it my machine main board version was "MEERK40T" and it thought that was fine.
I can't, however, know what a good response to Get Machine Status should be for the other controllers and I don't know any other Card IDs that do not raise any objections.
https://edutechwiki.unige.ch/en/Ruida
Hello, how are you? I have a laser RUIDA ... Can you help me to "decode" the RUIDA ACS android app? Thank you. Bruno Santos. Portugal.
The link I gave there gives all the commands. The app there is just controlling the laser through the UDP packets. It's just doing what any program controlling the Ruida would do. MeerK40t now allows for a ruida server, which will decode all the commands. If you really wanted to see exactly the commands the app is using. Download a copy of the app, and MeerK40t. Tell the app your Ruida laser is located at the computer running the MeerK40t ruidaserver and it'll tell you exactly the commands it's using. D9 00 and D9 01 are the main commands for moving the x and y. But, it'll let you see all the various other commands its using, since MeerK40t interprets all that stuff.
Then you'd make a similar app that just sends the same commands over UDP to the Ruida device. Basically writing your own Ruida controller software. Which isn't too hard to do. But, mostly you could interpret the app info with MeerK40t. ( https://github.com/meerk40t/meerk40t )
Thanks for your reply, I am very grateful! But I take the opportunity to expose some doubts ... I am trying to communicate with RUIDA and ARDUINO , sending udp packages to RUIDA. The wireshark software says it does not recognize the IP RUIDA being broadcast. Can you explain why? Will I have to send a hexadecimal to get communication? I can't find my RUIDA's IP and Mac address anywhere on my LAN ... I wonder why? Thank you.
Ohh!!! Camera?? Real time streaming? How does it work?
Basically in MeerK40t hit alt+F12 it'll start up the ruidaserver. Then you say whatever computer running it is a ruida device. It'll take any UDP data sent and parse out the hex into the data commands.
It's built to control an Lhystudios M2 Nano controller. But, one of the things to do is to interpret other boards so I could use RDWorks or Lightburn to control the M2 device. So it does all the parsing for the Ruida device to make that easier.
Basicamente, no MeerK40t, pressione alt + F12 e iniciará o ruidaserver. Então você diz que qualquer computador que esteja executando é um dispositivo ruida. Ele pega todos os dados UDP enviados e analisa o hexadecimal nos comandos de dados.
Sorry, I don't understand, or I didn't make myself understood. Can you tell how to communicate with RUIDA through ARDUINO? Directly from the arduino, not going through your RUIDA Server ... I loved your idea. Thanks, but as I've been doing this for 3 days, I didn't want to drop it, I would like to finally finish the communication, to really see how it is. How does RUIDA accept UDP? Because wireshark does not recognize the RUIDA IP ... Thank you.
With an arduino you'd have to connect through the COM port it has. Which would also work. Ruida devices have a internet connection and process UDP. You would wireshark when you connect to the Ruida device with RDWorks or Lightburn. If not over the net, the other connection method is COM port.
https://stefan.schuermans.info/rdcam/pc_conn.html
Unlike the UDP since I can fake it and do the research I don't have much info on how you'd do arduino com port connection stuff.
The interest would be to connect the arduino via Ethernet ... But for example, what is the 1 command sent to "activate" the RUIDA, that is, if you move the axes manually, in addition to the hex of the axes, first you have to go a hex to "activate" RUIDA, what is the hex that tells RUIDA that someone (arduino, PC, rpi) wants to connect to RUIDA?
There's not actually much to activation. You can see the handshaking when connecting RDWorks to a the fake server. Mostly you don't need most of that handshake stuff. You can generally just tell it to move. Here's a typical jog command:
--> da00057e (Get 05 7e (Card ID))
<-- b'\xda\x01\x05~\x06(\x01J\x00' (Respond 05 7e (Card ID) = 1694524672 (0x65006500))
<-- cc (checksum match)
--> da00057e (Get 05 7e (Card ID))
<-- b'\xda\x01\x05~\x06(\x01J\x00' (Respond 05 7e (Card ID) = 1694524672 (0x65006500))
<-- cc (checksum match)
--> da000004 (Get 00 04 (IOEnable))
<-- b'\xda\x01\x00\x04\x00\x00\x00\x00\x00' (Respond 00 04 (IOEnable) = 0 (0x00000000))
<-- cc (checksum match)
--> da00057e (Get 05 7e (Card ID))
<-- b'\xda\x01\x05~\x06(\x01J\x00' (Respond 05 7e (Card ID) = 1694524672 (0x65006500))
<-- cc (checksum match)
--> da000400 (Get 04 00 (Machine Status))
<-- b'\xda\x01\x04\x00\x00\x00\x00\x00\x16' (Respond 04 00 (Machine Status) = 22 (0x00000016))
<-- cc (checksum match)
--> da000026 (Get 00 26 (Axis Range 1, Get Frame X))
<-- b'\xda\x01\x00&\x00\x00\x13D\x00' (Respond 00 26 (Axis Range 1, Get Frame X) = 320000 (0x0004e200))
<-- cc (checksum match)
--> da000036 (Get 00 36 (Axis Range 2, Get Frame Y))
<-- b'\xda\x01\x006\x00\x00\r6`' (Respond 00 36 (Axis Range 2, Get Frame Y) = 220000 (0x00035b60))
<-- cc (checksum match)
--> da000021 (Get 00 21 (Axis Precision 1))
<-- b'\xda\x01\x00!\x00\x00\x00\x00\x00' (Respond 00 21 (Axis Precision 1) = 0 (0x00000000))
<-- cc (checksum match)
--> da000031 (Get 00 31 (Axis Precision 2))
<-- b'\xda\x01\x001\x00\x00\x00\x00\x00' (Respond 00 31 (Axis Precision 2) = 0 (0x00000000))
<-- cc (checksum match)
--> da00057e (Get 05 7e (Card ID))
<-- b'\xda\x01\x05~\x06(\x01J\x00' (Respond 05 7e (Card ID) = 1694524672 (0x65006500))
<-- cc (checksum match)
--> da00057e (Get 05 7e (Card ID))
<-- b'\xda\x01\x05~\x06(\x01J\x00' (Respond 05 7e (Card ID) = 1694524672 (0x65006500))
<-- cc (checksum match)
--> da000004 (Get 00 04 (IOEnable))
<-- b'\xda\x01\x00\x04\x00\x00\x00\x00\x00' (Respond 00 04 (IOEnable) = 0 (0x00000000))
<-- cc (checksum match)
--> da000020 (Get 00 20 (Axis Control Para 1))
<-- b'\xda\x01\x00 \x00\x00\x01\x00\x00' (Respond 00 20 (Axis Control Para 1) = 16384 (0x00004000))
<-- cc (checksum match)
--> c9020000030650 (Speed Laser 1 50.000000mm/s)
<-- cc (checksum match)
--> c6017f7f (Power 1 min=99.993896)
<-- cc (checksum match)
--> c6217f7f (Power 2 min=99.993896)
<-- cc (checksum match)
--> c6027f7f (Power 1 max=99.993896)
<-- cc (checksum match)
--> c6227f7f (Power 2 max=99.993896)
<-- cc (checksum match)
--> d900007f7f7f3170 (Move Origin X: -10000.000000 (-20000.000000,0.000000))
Most of the rest of that stuff can be dropped. Maybe not the laser speed but the laser power stuff. That's just syncing it with RDWorks.
What is "card ID" ? First connection to RUIDA? Enable connection to RUIDA? Does the raspberry pi 3 + handle 2 servers working? This and the other in java? How to find out the IP address and Mac address of RUIDA on the lan?
CardID is something or other. If RDWorks doesn't get 0x65006500 back which is the same as it writes 6500 it will disconnect and refuse to continue. It's actually what this thread originally was asking. What is the proper response to that query. It's called CardID and the correct response is 6500 with that you can also return zero for most of the rest of the stuff and it doesn't worry too much about it. Ghost's original question was the reply to DA 00 05 7E which is really DA 01 65 00 65 00. I'm not actually sure what it means other than the listing as CardID.
I think Ruida device itself gives you the IP address, somewhere. (I do not own a ruida device). You couldn't run MeerK40t's mock server and this one on the same IP because, by necessity, they use the same UDP port.
But think with me ... RUIDA receives 057e asks for communication, then RUIDA responds 0400 to say it is waiting for something? It is? As for the raspberry pi, I have a Java server running on it 24 hours a day, I was thinking of adding your server more, the IP of the RPI being different from RUIDA, of course.! I don't know if the 2 will work at the same time ... Obs... After hex, i used scramble and uncramble in ARDUINO code...
Hello, I already installed your software on Windows, very good ... Congratulations ... Opening the server, you really see the commands, :), but in reality I can't get the machine to work with your software as shown on YouTube ... Like the Android app, you cannot connect to the virtual RUIDA IP. I wonder why? Thank you
I wonder that too. I got a copy of the software for Android and I ran it and it didn't seem to even try to connect. It has my correct IP address and everything. There may be something different in the protocol like it's connecting to a different port somehow or doing something else, I might have to eavesdrop on the connection to figure out what's going on there. It should have been really easy, but somehow it's not connecting correctly. RDWorks works fine. The android app doesn't seem to do that.
I ran wireshark on the PC connection for data from the tablet to catch the incoming packets and the only thing from the right location was:
615 26.034262 192.168.1.118 192.168.1.167 UDP 60 40207 → 50207 Len=1 0xC
In console.py the line 1653:
port = 50200
So I changed that to:
port = 50207
And... it crashed. Since it's sending 0xCC which is an ACK packet it, but over UDP packets always tended to require checksums.
Also, 0xCC is ACK in the clear, without any swizzling. I replied 0xCC to it, and it said "Success!". So that's apparently the login sequence there. But, the protocol for the UDP here is a bit different than elsewhere.
The app has some specialty commands that are not actually seen elsewhere, and a different protocol on UDP 50207.
- +X key down
- \xa5P\x02
- +X key up
- \xa5Q\x02
- -X key down
- \xa5P\x01
- -X key up
- \xa5Q\x01
- +Y key down
- \xa5P\x03
- +Y key up
- \xa5Q\x03
- -Y key down
- \xa5P\x04
- -Y key up
- \xa5Q\x04
- +Z key down
- \xa5P\n
- +Z key up
- \xa5P\n
- -Z key down
- \xa5P\x0b
- -Z key up
- \xa5Q\x0b
- +U key down
- \xa5P\x0c
- +U key up
- \xa5Q\x0c
- -U key down
- \xa5P\r
- -U key up
- \xa5P\r
- Speed
- \xa5P\x11
- Start/Pause
- \xa5P\x06
- Stop
- \xa5P\t
- Reset
- \xa5PZ
- Trace On/Off
- \xa5P\x0f
- ESC
- \xa5P\x07
- Laser Gate
- \xa5P\x12
- Pulse key down
- \xa5P\x05
- Pulse key down
- \xa5Q\x05
- Origin
- \xa5P\x08
- Frame
- \xa5S\x00
Also, the Tablet sends \xce on regular intervals. I'm guessing it's a keep alive.
The 0xA5 command sends doesn't have a known meaning since it's wasn't registered in the code for the PC version rdworks.
The commands are typically P (0x50), except for some commands which have a key-up command too which is Q (0x51). Except for "Frame" which is 0xA5 S (0x53) It then has a command index.
So if you sent your Ruida over UDP on port 50207 0xA5 0x50 0x01 then 0xA5 0x51 0x01 it would start moving +X then stop. 0x02 is -X. 0x03 is +Y, 0x04 is -Y. Etc.
There is also a blank spot for current location of the laser in the app since I never sent back the right data. To get that correct it might require actually snooping on traffic between the tablet and the the controller.
Alright. Reverse Engineered most of that. Get a copy of the program circa 0.6.2 and the ruida server will also have a Ruida Jog Server which takes in those jog commands that the app sends out on port 50207. There's still an option on the Android device screen that says location and without capturing the app talking with the laser control, I'm not sure how that gets the information.
https://github.com/meerk40t/meerk40t/tree/0.6.2 (Added the jog server in just that branch).
--> a55006 (Interface Start/Pause)
<-- cc (ACK)
--> a55009 (Interface Stop)
<-- cc (ACK)
--> a5505a (Interface Reset)
<-- cc (ACK)
--> a5500f (Interface Trace On/Off)
<-- cc (ACK)
--> a55007 (Interface ESC)
<-- cc (ACK)
--> a55012 (Interface Laser Gate)
<-- cc (ACK)
--> a55005 (Interface Pulse Down)
<-- cc (ACK)
--> a55105 (Interface Pulse Up)
<-- cc (ACK)
--> a55008 (Interface Origin)
<-- cc (ACK)
--> a55300 (Interface Frame)
<-- cc (ACK)
--> a5500c (Interface +U Down)
<-- cc (ACK)
--> a5510c (Interface +U Up)
<-- cc (ACK)
--> a55003 (Interface +Y Down)
<-- cc (ACK)
--> a55103 (Interface +Y Up)
<-- cc (ACK)
--> a5500a (Interface +Z Down)
<-- cc (ACK)
--> a5510a (Interface +Z Up)
<-- cc (ACK)
--> a55001 (Interface -X Down)
<-- cc (ACK)
--> a55101 (Interface -X Up)
<-- cc (ACK)
--> a55011 (Interface Speed)
<-- cc (ACK)
--> a55002 (Interface +X Down)
<-- cc (ACK)
--> a55102 (Interface +X Up)
<-- cc (ACK)
--> a5500d (Interface -U Down)
<-- cc (ACK)
--> a5510d (Interface -U Up)
<-- cc (ACK)
--> a55004 (Interface -Y Down)
<-- cc (ACK)
--> a55104 (Interface -Y Up)
<-- cc (ACK)
--> a5500b (Interface -Z Down)
<-- cc (ACK)
--> a5510b (Interface -Z Up)
<-- cc (ACK)
So that's enough to replicate the Android App for whatever you are planning to do with that info.
Ohhh thank you for all work.
Amazing
Where are you from? :)
California, US.
NP on the work, I reverse engineer a lot of stuff so it's a bit easy at this point.
Corri o wireshark na conexão do PC para obter dados do tablet para capturar os pacotes recebidos e a única coisa no local certo era:
615 26.034262 192.168.1.118 192.168.1.167 UDP 60 40207 → 50207 Len = 1 0xC
No console.py da linha 1653:
port = 50200Então eu mudei isso para:
port = 50207E ... caiu. Como está enviando 0xCC, que é um pacote ACK, mas os pacotes UDP sempre tendem a exigir somas de verificação.
Além disso, 0xCC é ACK claro, sem qualquer swizzling. Eu respondi 0xCC e disse "Sucesso!". Então essa é aparentemente a sequência de login lá. Mas, o protocolo para o UDP aqui é um pouco diferente do que em outros lugares.
I understood that I don't need to swizzle on the Arduino and that the commands to be sent to RUIDA are without swizzling, do you agree?
O aplicativo possui alguns comandos especiais que na verdade não são vistos em outros lugares e um protocolo diferente no UDP 50207.
Tecla + X pressionada
- \ xa5P \ x02
Tecla + X acima
- \ xa5Q \ x02
Tecla -X pressionada
- \ xa5P \ x01
Tecla -X
- \ xa5Q \ x01
Tecla + Y pressionada
- \ xa5P \ x03
Tecla + Y para cima
- \ xa5Q \ x03
-Y tecla pressionada
- \ xa5P \ x04
Tecla -Y
- \ xa5Q \ x04
Tecla Z + pressionada
- \ xa5P \ n
- Tecla Z para cima
- \ xa5P \ n
-Z tecla pressionada
- \ xa5P \ x0b
Tecla -Z
- \ xa5Q \ x0b
- Tecla U pressionada
- \ xa5P \ x0c
- Tecla U para cima
- \ xa5Q \ x0c
-U tecla para baixo
- \ xa5P \ r
Tecla -U
- \ xa5P \ r
Rapidez
- \ xa5P \ x11
Iniciar / Pausar
- \ xa5P \ x06
Pare
- \ xa5P \ t
Redefinir
- \ xa5PZ
Rastreamento ativado / desativado
- \ xa5P \ x0f
ESC
- \ xa5P \ x07
Laser Gate
- \ xa5P \ x12
Tecla de pulso pressionada
- \ xa5P \ x05
Tecla de pulso pressionada
- \ xa5Q \ x05
Origem
- \ xa5P \ x08
Quadro, Armação
- \ xa5S \ x00
Além disso, o Tablet envia
\xceregularmente. Eu estou supondo que é manter vivo.
Different UDP protocol? As well?
Yeah, the UDP is in the clear without checksum and without swizzle. It's also on port 50207 and replies are made to the sending port on port 40207.
If you make an app that sends a UDP from port 40207 to 50207 on the Ruida device and send one of those preset packets, it should duplicate the app functionality.