Aug 12 2004

Veo.pm – a perl module to talk to the Veo Observer Network Cameras

Thanks to Brian G I finally found a way to talk to the Veo Observer Network Cameras from any platform that supports perl. As mentioned before I tried to stream images from the camera using a FreeBSD system, however the software supplied by Veo only supports Windows. I spent some time trying to decode the data I received from the camera, but did not have any luck.

Yesterday, Brian G emailed me and asked me a question related to the article above. In passing he mentioned that he had received a response from Veo about the file-format. One email later I had the Veo-response in my hands and guess how suprised I was when I read this: the data delivered from the camera is in JPEG format, it only misses a JPEG header!!! DUH!!!

Along with the email I also received a 400 byte binary file with the header. After a few more hours of work (tacking on the header was not enough), I received my first full frame from the camera. I was happy to see that my decoding efforts were pretty darn close to the information that Brian forwarded.

So now I (and you) can access those cameras from any platform that supports perl and the IO::Select and IO::Socket modules.

Here’s a little sample script that saves 10 frames at 640 x 480 at 1 frame/sec:

#!/usr/bin/perl -w

use strict;
use Veo;

my $veo=Veo->new(host => ‘192.168.1.1’, port => 1600);
$veo->login(user => ‘admin’, password => ‘password’);
my($images)=10;
$veo->selectStream(Veo::VEO_STREAM_640X480,1);
$veo->stream(\&cb);

sub cb {
    my($type,$frame,$data)=@_;
    print STDERR qq{image $frame with },length($data),qq{ bytes\n};
    open(OUT,”>”.sprintf(“veo-%02d.jpg”,$images));
    binmode(OUT);
    print OUT $data;
    close(OUT);
    # return value > 0 indicates “keep on streaming”
    # return value = 0 indicates “stop streaming”
    return $images–;
}

Easy – isn’t it?

And here’s another sample. This time we use the move() method to pan the camera head and take pictures after each step. This script will logon to the camera, move the head all the way to the left and then slowly move to the right while taking a single frame after each step to the right.

#!/usr/bin/perl -w

use strict;
use lib “.”;
use Veo;

my $veo=Veo->new(host => ‘192.168.1.1’, port => 1600);
$veo->login(user => ‘admin’, password => ‘password’);
$veo->selectStream(Veo::VEO_STREAM_320X240,1);
my($rc);
# move all the way to the left
while($rc=$veo->move(Veo::VEO_MOVE_FULL_LEFT)) {
    last if($rc != Veo::OK);
}
# now take one frame at a time and move right
do {
    $veo->stream(sub {
                     # args are: frametype, framenumber, framedata
                     open(OUT,”>frame-“.sprintf(“%04d”,$_[1]).”.jpg”) || return 0;
                     binmode(OUT);
                     print OUT $_[2];
                     close(OUT);
                     return 0;
                 });
    $rc=$veo->move(Veo::VEO_MOVE_RIGHT);
} while($rc == Veo::OK);

As it says in the documentation of the module, I’m going to finish this up over the next few days, but I’ve been asked soo often that I decided to release this piece half-baked. Have fun with the Veo.pm (right-click, save as …, the usual) perl module and let me know if it works or doesn’t work for you.

Update 8/16/2004:

James A. Russo quickly converted the perl-module into something Java-people can use. Hop on over to http://www.halo3.net/ to find the Java-classes and some more information. James also used the Veo.pm perl module in a quick perl CGI to retrieve images from the camera and move the camera position. Here it is (thanks James):

#!/usr/bin/perl

# webveo.pl – James A. Russo jr@halo3.net – August 14th, 2004.
#
# Quick and dirty script allowing a Veo Observer Network Camera to be used from a simple web page.
#
# It will redirect you to the $URL variable when moving. So a simple webpage like this should work:
#
# …
# <img src=”/path/to/webveo.cgi?action=getimage”>
# <a href=”/path/to/webveo.cgi?move=fullup”>Move Up</a>
# …
#
#
# This script uses Veo.pm from Tobias Hoellrich. See http://www.kahunaburger.com/blog/archives/000157.html for more info.
#

use CGI;
use Veo;
use Fcntl qw/ :flock /;

my $USER = “admin”;
my $PASSWORD = “password”;
my $HOST = “192.168.1.142”;
my $PORT = 1600;

# Other options for STREAM.
# Veo::VEO_STREAM_640X480;
# Veo::VEO_STREAM_160X120;
my $STREAM = Veo::VEO_STREAM_320X240;
my $URL= “index.html”;

## Nothing below this line needs editing..

my $CGI = new CGI;
my $ACTION = $CGI->param(‘action’);
my $MOVE = $CGI->param(‘move’);

# We synchronize since two admins can’t log in at once.
open FL, “>.lock” || die “Unable to open lock file.”;
flock(FL,LOCK_EX);

my $VEO = Veo->new(host => $HOST, port => $PORT);

$VEO->login(user => $USER, password => $PASSWORD);

if ($MOVE) {
    if ($MOVE eq “up”) {
        $VEO->move(Veo::VEO_MOVE_UP);
    } elsif ($MOVE eq “fullup”) {
        $VEO->move(Veo::VEO_MOVE_FULL_UP);
    } elsif ($MOVE eq “down”) {
        $VEO->move(Veo::VEO_MOVE_DOWN);
    } elsif ($MOVE eq “fulldown”) {
        $VEO->move(Veo::VEO_MOVE_FULL_DOWN);
    } elsif ($MOVE eq “left”) {
        $VEO->move(Veo::VEO_MOVE_LEFT);
    } elsif ($MOVE eq “fullleft”) {
        $VEO->move(Veo::VEO_MOVE_FULL_LEFT);
    } elsif ($MOVE eq “right”) {
        $VEO->move(Veo::VEO_MOVE_RIGHT);
    } elsif ($MOVE eq “fullright”) {
        $VEO->move(Veo::VEO_MOVE_FULL_RIGHT);
    }
    $VEO->logout;
    print “Location: $URL\n\n”;
} elsif ($ACTION eq “getimage”) {
    $VEO->selectStream($STREAM,1);
    $VEO->stream(\&image_cb);
    # callback will be called once, and then we will get here..
    $VEO->logout;
    # unflock happens on exit..
    exit(1);
} else {
    print “Content-type: text/html\n\n”;
    print “Unknown action: $ACTION\n”;
}

sub image_cb {
    my($type,$frame,$data)=@_;
    print “Content-type: image/jpeg\n\n”;
    print $data;
    # We only want the one image…
    return 0;
}

28 Responses to “Veo.pm – a perl module to talk to the Veo Observer Network Cameras”

  • aal27 Says:

    how r u using the VEO object? where is the VEO object defined
    thanks

  • Mark Says:

    Awesome, you guys are great! I have been waiting for someone to hack the network protocol on the veo observer ever since I bought mine.

  • Miguel Says:

    You made my day. Thank you so much.

    BTW, Veo should be happy too as they will be selling more units as a result of this. Customers are no longer locked to use Win*

  • UnKnOwN Says:

    Thank you very much for this nice little perl module.

    A good thing would be to integrate this functionality into the ROM of the camera… It would be so easy for veo. They already have tiny webserver to process HTTP GET. And adding the JPEG header to the image delivery is really not a big issue.

    If not… I will start to put my fingers on it (and I’m a really nasty guy which usually unsolders flash ROMs for read outs)

  • sogood007 Says:

    It is awesome. I was thinking to sell the Veo because the ActiveX requirement. Now I can finally use it. I wonder any possibility to integrate with program like motion or zoneminder.

  • mark Says:

    What would be neat, is too see an example of transcoding the video stream into something else. Like real-time transcoding into a streaming video format, that is more user friendly and cross platform.

    Also as to hacking the firmware, good luck. I opened mine up right after getting it and it uses a custom RISC processor chip. Which will be hard to figure out, since there are no datasheets available for it.

  • Phil Says:

    It worked :-) You star!

  • Ken Says:

    Thank you!!! That rocks!!!

    I’m hoping to find the time to port it (probably the Java translation) to C++ but for now your command-line program along with a batch file actually makes the camera useful again!

  • Jon Says:

    Thanks to all the work you’ve done on this. It’s been a great help in making the camera more useful. It’s also kick started my first foray into Perl too.

    Has anyone figured out a way to get the camera to pan/tilt to a precise position? I want to retain the ability to move the camera, but there is also a specific snapshot that I want to get once a day.

    The only method I’ve come up with is to “baseline” the camera by sending it all the way left and down, and then bringing it up and right a set amount. The problem I’m finding is that it’s not accurate. The camera is always a degree or two off each time.

    I’m using a ‘for’ loop to control the number of increments to move, with a sleep inside each loop to alet the camera complete each movement. I also use ‘sleep’ to let the camera complete each increment, but I don’t know how far the camera actually moves in each increment and I don’t think sleep is very precise. Any ideas appreciated. jxplatt@hotmail.com

    Psuedo code (because pasting perl here doesn’t seem to work very well):

    for $pos = 1 to 30
    {
    $rc=$veo-move(Veo::VEO_MOVE_UP);
    last if ($rc != Veo::OK);
    sleep(1);
    }

  • Tobias Hoellrich Says:

    Jon – I’ve also noticed that movement-control in the Veo is not very accurate. I have two suggestions.
    1) You may want to try different “baseline points”. Try going all the way right and up (or right/down, left/up) and offset from there. Perhaps movement is more predictable from another point
    2) The second suggestions is a bit more involved, but should be a lot more accurate. This would involve calibrating the camera based on what the camera “sees”. The idea is that you get roughly into the area where the camera should be positioned to. You would then analyze the current image (by downloading a frame from the camera) and looking for a certain pattern that manually provided in the frame (a red dutct tape mark, a spot or something else that is easily detected in the frame). You would then move the camera until the calibration mark appears exactly in the location where you would expect it.

    Hope this helps
    –Tobias

  • Robert Eden Says:

    Thanks for the module. I’m going to use it to make a time-lapse video of the construction of my pool!

    I’ve found a bug. In module stream, you don’t check the status of the call to _recvmsg. Occassionally, I get an error and the program loops. I just copied the croak code from the other _recvmsg calls.

    I’m asking the camera for a 640×480 stream. Sometimes it gets the resolution wrong. My code detects it and reconnects.

    I’ll post my code shortly for others to see. It captures a 640×480 page every x seconds, uses ImageMagick to add a timestamp, and then saves the file to disk (timestamp filename).

    If there is interest, I’ll set up a Yahoo! group for discussions with this camera. Is there already a forum? (other than this blog)

    I already have some modules on CPAN, have you thought of submitting it? If you don’t want to, I can.

    Robert

  • cwhong Says:

    Help!!! I am a newbie at cgi and Perl, and can’t get this script to work for the life of me! I am using the webveo.cgi script (the one shown near the end of this page)

    When I run the script from the command line:
    ******** ~/public_html/cgi-bin$ perl webveo.cgi
    No response from camera at webveo.cgi line 53

    I have checked and rechecked the login info, and the camera pings fine, and the IP and port are correct. I don’t know what to do from here. Any suggestions?

  • Gus Fraser Says:

    Fantastic work guys, this ia awsome stuff THANKYOU

  • cfh Says:

    since the output of the sample script are jpg images you can modify it so it will generate the same filename every time and then with the help of server-push:

    http://web.they.org/software/php-push.php
    http://www.radzone.org/tutorials/animatep.html

    you can see your netcam from a website and work around the limitation of one user logged in at a time.
    I’ve tried it and it works great.
    Thanks for this software!
    And don’t forget to try the java version from James A. Russo, it’s great too!

  • Serge Says:

    Re. the java version from James. A. Russo, I get an error when running it: “failed to load main-class manifest attribute from…JVeo-0.2.jar”. Obviously I’m not competent on this matter and therefore any help would be greatly appreciated.
    Thanks – Serge

  • D Says:

    tried server push, but it’s not very smooth on the updates, the images go blank and then load from the top down, not really like watching a video stream. does the java version fare any better for streaming?

  • Kevin Says:

    I’d like to say a great big thank you as well! This cam has been dormant for a year and now its going to get put back online and in use! I’ve been waiting for this for a long time as well. Thanks so much for the time spend getting this working

  • Thoneter Says:

    Does anyone know how to redo the firmware? I’ve tried with the software and clicked the update button but I get a protocol error. When I look at the users it shows nothing in the user list. Thanks for all the posts! TT

  • Vinod Pathangay Says:

    Thanks.. it works well. There was some problem copying the code on this page to vim (the character ” gets changed). Was able to get it running anyway..

  • Mike Zwetsloot Says:

    Hey, it looks good but i dont understand exally how to add it all to my webpage, do i only have to implet the java code to my webpage?

    Hope someone cam help me please.
    Kind regards, Mike Zwetsloot mzwetsloot@yahoo.com

  • Dan Says:

    Can someone please elaborate on how this (the perl or java or whatever) is implemented? Do I just copy the code to my webserver’s directory and then go to town? Do I somehow flash this to the camera’s firmware (wouldn’t that be cool)? I’m just lost on that and don’t know much about perl and nothing about java to have the time to decipher all the code to figure out how it works.

    Also, I would like to be able to issue commands (via commandline) to the camera from a PC (internally or externally of the LAN) to automate processes through a program called girder. I basically want event triggering….say as a result of somehting happening, move the camera and take 10 seconds of video.

    Is there a way to listen for audio (kinda like motion detection) and then use that to trigger something else? I see potential for a baby monitor….basically if a noise is heard at a certain level, have an event/argument sent to a certain PC that then issues a command to start shooting video and turn the tv on.

    Anyone have any insight on all of my ramblings? Thanks! Email below:

    debennett2@gmail.com

  • Lou Steinberg Says:

    First…thanks. I’ve been using the perl module for a while. My veo watches the oil level in a remote cottage as well as the temperature under the house. Works great.

    One challenge is that I’ve never gotten the camera to take pictures in 640×480 mode. Seems stuck on 320×240. Anyone else found this?

    Lou

    Mike…did you ever get your web page to work? If not, let me know and I’ll send you what I did.

    PS…just to document it here, one thing that threw me for a while was I moved the IP addresses of my cameras (since I had 2). Doing so changes the port number that it listens on!

  • wrybread Says:

    I just picked one of these (wired) up from a thriftshop for $15… Was really excited, I’ve always wanted to mess around with one of these. Glad to have found this page too, if I have to access this with IE it’s pretty much useless to me.

    Wondering if anyone has ported this to python? If so please email wrybread AT gmail dot you know what.

  • San Says:

    I’m having problem with my veo wired camera. it says protocol error and wont let me sign on? what’s going on. help please

    thanks
    San

  • Ruben Says:

    I have tried all the utils, soft and SDK, but none of them works with my Veo Observer XT. I have upgraded the firmware and the your Veo download JPG utility doesn’t works, it tell me wrong protocol. Any idea to solution this?

    Thanks very much.
    Ruben

  • Mike P. Says:

    I’ve wanted this for a very long time. Thanks for making the Veo useful! “The force is strong with this one…”

  • Ivan Drake Says:

    It is a long time since there were any posts on this site.
    I am trying to use my old Veo Observer XT but get the message VeoNetCam ActiveX Control v2.065 download failed.

    Is there an way I can recover from this.

    Thanks

    Ivan

  • Mirko Doelle Says:

    You made my day, guys!

    A kollegue gave me the Veo camera for supervising a hall — not mentioning how old it is, and of course he forgot to tell me that a) the CD was broken while repacking and b) Veo is out of business for a long time.

    Struggling over the known ActiveX problems in IE (running Windows XP in a virtual machine under Linux), I was absolutely sure to have a new paperweight.

    But after replacing all the problematic characters in the perl code on this site, I got the first pictures from the camera.

    Well done, thanks a lot!

    Mirko

Leave a Reply