![]() |
Hacking the Veo Observer |
Version 1.2
August 13th, 2004
The wife went out and bought me one of these for christmas, likely because I have always been into web cameras ever since I build my own servo camera mount back in 1998. My only problem with the camera is that there is no ability to obtain the video with anything except the software they provide, or by using the windows SDK. I spent an afternoon with a sniffer trying to figure out the protocol and I have a bunch of it decoded, and some java code to control the camera, my only problem is trying to determine the video format from the camera.
The camera actually contains an Xirlink "Network Camera" engine. You can find their example NetCap application including source code here. This provides all the functionality which was duplicated by the Veo software. Both likely use the same DLL. The help file included with the Xirlink SDK seems to cover all the functions which are available and their arguments. This could likely be very helpfull.
Please contact me at jr<at>halo3.net if you can help me figure out anything on this project, especially relating to the image decoding.
Updated - August 13th, 2004
We figured it out! The image is nothing more then just a JPEG without the header. You need to construct your own heaer in order for it to work! Tobias has written a Perl module, and I took this Perl module and wrote a quick Java API and example Swing application. It can be downloaded here:
http://www.halo3.net/projects/veo/jveo
Tobias' has his perl module listed on this website:
http://www.kahunaburger.com/blog/archives/000157.html
I will likely also be writting a quick CGI using Tobias' VEO.pm perl module. To stay tuned.
Updated - May 12th
Found out some additional information. There is someone else who has worked on this project back in february. You can see their blog entry here:http://www.kahunaburger.com/blog/index.html
Here has some dumps of black and white frames which might provide more information on decoding.
Connection Details
The camera is controlled via TCP on (web port + 1520) . If you move the web access port, the video/control port moves by the same amount. I have mine on port 8181, so the port is 9701.
The first command sent on this port must be the login command. The camera does contain ACLs as some guest users won't have camera control ability, etc. The listing of all commands I have decoded are contained below. Once connected you are able to send commands and recieve responses.
Once connected, you can send the following commands with each expecting a response.
The general packet format appears to be:
| 2 bytes | 1 byte | 1 bytes | n bytes |
| Length | Command | Sequence | Command Specific Data |
The sequence is used to sync up commands to responses. The response to your command will always contain the same sequence number as the command you sent.
Here is a listing of the commands I have been able to decode thus far. I will add to this list once I get some more time.
Image Decoding
This is by far the most important aspect to tackle, the ability to obtain images from this camera will open up many possibilities. The frames of data all appear to be under the typical MTU limit of 1452.
I was able to get some binary data from the camera, when it was put in "send images" mode, but I am not able to decode or understand their content. You can download these "frames" here. frame1 frame2 frame3 frame4 frame5 They appear to follow a similar format of the other packets, where the first few bytes is the length of the frame, etc. They all appear to start out the same, etc.
Audio Decoding
The camera does have a built-in microphone which is able to send audio along with the video images. I assume that these are just another "packet" of data.
Login Packet (cmd=0x00)
I haven't fully decoded the login packet, but here is the data which works:
0000000: 0084 0000 6164 6d69 6e00 0000 aa02 0000 ....admin.......
0000010: e8f2 1200 691d d577 0000 0400 0000 0000 ....i..w........
0000020: 0000 0000 e02d 7301 0000 0000 0000 0000 .....-s.........
0000030: 0300 0000 3608 b402 10f3 1200 b447 d477 ....6........G.w
0000040: 602c 9a00 7061 7373 776f 7264 0047 d477 `,..password.G.w
0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000060: 68f3 1200 9f58 f777 20f3 1200 1800 0000 h....X.w .......
0000070: 602c 9a00 0300 0000 0000 0000 0000 0000 `,..............
0000080: e02d 7301 .-s.
Also contained in the login packet is the language information since that is present on the login form.
Likely don't need to know exactly what all of it does.
The full login packet for the default user is available for download here
Camera Movement (cmd=0x15)
Request
Size |
Cmd |
Sequence |
Direction |
0x0005 |
0x15 |
0x## |
<see table> |
| Move Up | 0x00 |
| Pan Up | 0x01 |
| Move Down | 0x02 |
| Pan Down | 0x03 |
| Move Left | 0x04 |
| Pan Left | 0x05 |
| Move Right | 0x06 |
| Pan Right | 0x07 |
The difference between Move/Pan is that the pan command covers more distance, the move is just one 'tick'.
Response:
Success: (not at end of travel)
Size |
Results |
Sequence |
0x0004 |
0x04 |
0x## |
Failure: (at end of travel)
Size |
Results |
Sequence | ?? |
0x0005 |
0x05 |
0x## | 0x12 |
Motion Detection Status (cmd=0x12)
Request:
Size |
Cmd |
Sequence |
0x0005 |
0x12 |
0x## |
Response:
Size |
Results |
Sequence |
Value |
0x0005 |
0x04 |
0x## |
0x00=off, 0x01=on |
Get Email Properties (cmd=0x0b)
Request:
Size |
Cmd |
Sequence |
0x0004 |
0x0b |
0x## |
Response:
Size |
Results |
Sequence |
?? | IP Address (4 bytes) |
Attach Image | reset time (4 bytes) | From (64 bytes, NULL Terminated) | To (64 bytes, NULL Terminated) | Subject (64 bytes, NULL Terminated) | Message Body (256 bytes,NULL Terminated) |
0x0005 |
0x04 |
0x## |
0x02 | 0xabcdef |
0x00=true,0x01=false | 0x00000000 |
Set Email Properties (cmd=0x0c)
Request:
Size |
Cmd |
Sequence |
?? | IP Address (4 bytes) |
Attach Image | reset time (4 bytes) | From (64 bytes, NULL Terminated) | To (64 bytes, NULL Terminated) | Subject (64 bytes, NULL Terminated) | Message Body (256 bytes,NULL Terminated) |
0x0005 |
0x0c |
0x## |
0x02 | 0xabcdef |
0x00=true,0x01=false | 0x00000000 |
Response:
Size |
Results |
??? |
Sequence |
0x0004 |
0x04 |
0x04 |
0x## |
Get Camera Information (cmd=0x09)
Request:
Size |
Cmd |
Sequence |
0x0002 |
0x09 |
0x## |
Response:
Size |
Results |
Sequence |
Camera Name (64 bytes) |
Camera Location (64 btyes) |
0x0084 |
0x04 |
0x## |
Set Camera Information (cmd=0x0a)
Request:
Size |
Cmd |
Sequence |
Camera Name (64 bytes) |
Camera Location (64 btyes) |
0x0084 |
0x04 |
0x## |
Response:
Size |
Results |
Sequence |
0x0004 |
0x04 |
0x## |
Get Lighting (0x07)
Request:
Size |
Value |
Sequence |
0x0005 |
0x07 |
0x## |
Response:
Size |
Results |
Sequence |
Backlight Value |
0x0005 |
0x04 |
0x## |
0x## |
Set Lighting (0x08)
Request:
Size |
Cmd |
Sequence |
Backlight Value |
0x0005 |
0x08 |
0x## |
0x## |
Response:
Size |
Results |
Sequence |
0x0005 |
0x04 |
0x## |
Get Brightness (0x05)
Request:
Size |
Value |
Sequence |
0x0005 |
0x05 |
0x## |
Response:
Size |
Response |
Sequence |
??? (3 bytes) |
bright ness value |
0x0005 |
0x04 |
0x## |
0x000000 |
0x## |
brightness value only appears to go from 0..23
Set Brightness (0x06)
Request:
Size |
Cmd |
Sequence |
??? (3 bytes) |
brightness value |
0x0005 |
0x06 |
0x## |
0x000000 |
0x## |
brightness value only appears to go from 0..23
Response:
Size |
Response |
Sequence |
0x0005 |
0x04 |
0x## |