Click here to Skip to main content
Click here to Skip to main content
Go to top

Cam Alarm 2.0 - Alarm system run from a web camera

, 16 Jun 2010
Rate this:
Please Sign up or sign in to vote.
Simple alarm system for those on a budget..

main.jpg

Just a quickie..

I wrote the original version of this in VB6 about 4 years ago, and published it as freeware (might even be floating around the wild somewhere still..), and decided it was a good starter app for learning C#, when I began migrating my skills almost two years ago. So, the uncompleted version of this has been sitting in a folder on my dev box for some time, just waiting for a few tweaks - which I got around to the other day. I thought this would be a good target freeware, because unfortunately, many of us have had the misfortune of being robbed at some point in our lives, and students, young working people, or someone in an apartment may not be able to afford or install a proper alarm system.

I use a Creative 5.1 speaker rig, and with the amp cranked, the siren this sounds is at least as loud as a conventional alarm system, and would probably cause an intruder to bolt rather than attempt to find the source and disarm.

The original used the avicap32.dll library, which seemed to work fine on my older Logitech camera, but will not work on newer devices (this was tested with both an Acer notebook camera, and an MS Lifecam). At this point, I realized I had to go to the DirectShow library to capture video from a wider range of input devices. A search on CodeProject turned up the Motion Detection project by Andrew Kirillov. I removed dependencies on the AForge library, and reworked the AVI reader/writer classes, but the DirectShow wrappers and detection algorithms are his work (thanks Andrew).

The highlights

When the application loads, it tests for the WMV AVI recording codec by enumerating the installed codecs; if it isn't found, a dialog is launched, asking the user to install it. The installation executable is an embedded resource, which is pulled from the resource assembly and recreated as a file in the temp directory, then launched with the ShellExecute API.

private void codecTest()
{
    FilterCollection filters = new FilterCollection(FilterCategory.VideoCompressorCategory);
    bool found = false;
    foreach (Filter filter in filters)
    {
        found = filter.Name.Contains("Media Video 9");
        if (found)
            break;
    }
    if (!found)
    {
        if (MessageBox.Show("The video capture feature requires the Microsoft " + 
            "WMV9 codec. Do you want to install this now?", 
            "Codec Installation Required",
            MessageBoxButtons.OKCancel, 
            MessageBoxIcon.Question) == DialogResult.OK)
        {
            executeCodec();
        }
        else
        {
            _bCanRecord = false;
        }
    }
}

private bool executeCodec()
{
    try
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        using (Stream stream = assembly.GetManifestResourceStream(
                               "CamAlarm.Resources.wmv9VCMsetup.exe"))
        {
            if (stream != null)
            {
                BinaryReader br = new BinaryReader(stream);
                using (FileStream fs = new FileStream(
                       Environment.GetEnvironmentVariable("TEMP") + 
                       "\\wmv9VCMsetup.exe", FileMode.Create))
                {
                    BinaryWriter bw = new BinaryWriter(fs);
                    byte[] bt = new byte[stream.Length];
                    stream.Read(bt, 0, bt.Length);
                    bw.Write(bt);
                    br.Close();
                    bw.Close();
                    fs.Close();
                }
                executeProgram(Environment.GetEnvironmentVariable("TEMP") + 
                               "\\wmv9VCMsetup.exe");
            }
        }
        return true;
    }
    catch { return false; }
}

A timer is run that waits for the camera to focus in, then the control panels are activated. Settings like the keycode and option control states are stored in the application's default properties. When first run, or if the keycode property is cleared, the Arm/Disarm button acts as the keycode set button. The sounds used in the application are instances of the System.Media.SoundPlayer class, instanced and loaded with a sound file when the app initializes:

private void loadWarning()
{
    if (_cWarningSound != null)
        _cWarningSound.Dispose();
    _cWarningSound = new SoundPlayer(CamAlarm.Resource1.beep);
    _cWarningSound.Load();
}

The camera's motion trigger-state is polled periodically using a custom timer class; if motion has occurred, an alarm timer is fired, which will loop until the alarm is deactivated, or the max alarm timeout occurs:

private void _cAlarmTimer_Tick(object sender)
{
    // timer starts 5 states: standby, armed, arming, triggered, sounding
    //1) if arming warning period elapses, optional beeps
    //2) if not arming, warning sounds and counts to min elapse
    //3) if min elapse and _activetick over threshhold, loops again
    //4) if standby -stop timer
    if (_eAlarmState == AlarmState.Arming)
    {
        _iTimerTick++;
        if (_iTimerTick > stringToInt(txtArmingDelay.Text))
            armAlarm();
        else
            updateStatus();
    }
    else if (_eAlarmState == AlarmState.Armed)
    {
        if (_iActiveTick > 5)
            triggerAlarm();
    }
    else if (_eAlarmState == AlarmState.Sounding)
    {
        _iTimerTick++;
        if (_iTimerTick > stringToInt(txtDuration.Text))
        {
            if (_iActiveTick < 5)
                disarmAlarm();
            else
                //loop again
                soundAlarm();
        }
        else
        {
            soundAlarm();
        }
    }
    else if (_eAlarmState == AlarmState.Standby)
    {
        stopAlarm();
    }
    else if (_eAlarmState == AlarmState.Triggered)
    {
        _iTimerTick++;
        if (_iTimerTick > stringToInt(txtAlarmDelay.Text))
        {
            soundAlarm();
        }
        else
        {
            if (!chkSilent.Checked)
                playWarning();
        }
    }
}

When the alarm is in Armed mode, all but the keypad and disarm switch are disabled. This is done by disabling the GroupBox that houses the controls. The main form close button also needs to be deactivated. This is done both by cancelling the form's exit in the FormClosing event, and by disabling the Close button using the GetSystemMenu/EnableMenuItem API:

private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
    if (_bCloseDisabled)
    {
        e.Cancel = true;
    }
    else
    {
        closeCamera();
        closeFile();
        saveSettings();
        if (_cAlarmTimer != null)
            _cAlarmTimer.Dispose();
    }
}

private void enableClose(bool enable)
{
    if (enable)
        EnableMenuItem(GetSystemMenu(this.Handle, false), SC_CLOSE, MF_ENABLED);
    else
        EnableMenuItem(GetSystemMenu(this.Handle, false), SC_CLOSE, MF_GRAYED);
    
    _bCloseDisabled = !enable;
}

All in all, fairly simple approach; though I wasn't all that generous with comments in code, it is fairly straightforward..

Using the application..

Keep the camera view up where pets won't trigger it, and away from windows. Crank the volume on your speakers, and adjust application volumes through the mixer; CamAlarm has an option to push to the maximum volume when the alarm is activated, but this won't mean much if the master volume is down low.

Well.. enjoy! If you find any bugs, be sure to leave a message.

Change log

May 17, 2010

  • First time loading of help page creates page in user app folder.
  • Alarm volume raised after triggering warning beeps.
  • Fixed lock when capturing video, changed from Monitor.Enter to TryEnter in Camera.cs.
  • Added tooltip to Clear and Video buttons.
  • Added menu buttons to disabled items when alarm is activated.

June 16, 2010

  • Fixed codec URL in executeCodec().
  • Fixed disabled OK button in device selection form.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

John Underhill (Steppenwolfe)
Network Administrator vtdev.com
Canada Canada
Network and programming specialist. Started in C, and have learned about 14 languages since then. Cisco programmer, and lately writing a lot of C# and WPF code, (learning Java too). If I can dream it up, I can probably put it to code. My software company, (VTDev), is on the verge of releasing a couple of very cool things.. keep you posted.

Comments and Discussions

 
GeneralMy vote of 5 Pinmemberthatraja23-Sep-10 2:02 
GeneralCompression Pinmemberbelzer8-Jul-10 14:44 
Hello,
 
Nice work! I played with it quite a bit, but when it records it doesn't seem to be using compression - why do you download the wmv9 codec if it isn't being used? (or is something wrong by me that it is not using compression?)
 
Thanks,
Yanky
GeneralInclude or exclude areas Pinmemberchinkuanyeh28-Jun-10 9:32 
GeneralRe: Include or exclude areas PinmemberSteppenwolfe5-Jul-10 14:17 
GeneralAVIMakeCompressedStream // -- fails PinmemberMU Jon Frost9-Jun-10 17:22 
GeneralRe: AVIMakeCompressedStream // -- fails PinmemberSteppenwolfe10-Jun-10 2:18 
GeneralHidden electricity costs PinmemberS.H.Bouwhuis24-May-10 21:51 
GeneralRe: Hidden electricity costs PinmemberSteppenwolfe25-May-10 4:15 
GeneralNew version 2.1 PinmemberSteppenwolfe17-May-10 11:24 
GeneralWhow Nice Pinmemberredspiderke17-May-10 6:51 
GeneralRe: Whow Nice PinmemberSteppenwolfe17-May-10 11:19 
QuestionNice aticle! 5 from me. PinmemberBryanWilkins17-May-10 5:28 
AnswerRe: Nice aticle! 5 from me. PinmemberSteppenwolfe17-May-10 5:42 
GeneralNice article PinmemberJitendra Zaa17-May-10 2:44 
GeneralRe: Nice article PinmemberSteppenwolfe17-May-10 5:42 
GeneralGreat Article.. PinmemberGaurav Dudeja India16-May-10 19:32 
GeneralRe: Great Article.. PinmemberSteppenwolfe17-May-10 5:43 
GeneralLooks Interesting .... PinmemberGarth J Lancaster16-May-10 12:12 
GeneralRe: Looks Interesting .... PinmemberSteppenwolfe16-May-10 12:21 
GeneralRe: Looks Interesting .... PinmemberGarth J Lancaster16-May-10 12:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 16 Jun 2010
Article Copyright 2010 by John Underhill (Steppenwolfe)
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid