October 2010,

Some notes on using DDE to control blue iris.

The BlueIris GUI does a lot but when external triggers or remote control are required a DDE (direct data exchange) interface can be used.

One requirement I have is to be able to trigger cameras using something like PIR motion sensors in places where false triggering occurs when using the video motion detection. PIR and other sensor can also work in the dark.
Another thing I need is a way to disable the system remotely when I come home.

DDE is considered to be an out of date legacy protocol by most people so support for it is limited.

Blue iris has a DDE server built into it and several console mode programs can be downloaded for free to trigger cameras etc.

Quote from cam-it.org

BI Command is designed to use Blue Iris DDE commands for external call.

Usage:

bicommand.exe etc.

You can use as many camera short names as you want, and which are available.

Available commands:

trigger: triggers an motion event - will call set up alerts
recstart: starts manual recording of the camera(s)
recstop: stops manual recording of the camera(s)
snapshot: takes a snapshot of the camera(s) and stores it in the recording folder
reset: resets the camera(s)
enable: enables the camera(s)
disable: disables the camera(s)

Example "bicommand.exe snapshot cam1 cam2 cam3"

End quote.

Other commands include "red" "yellow" "green" to change the state of the signals.
For example sending the command "red" will disable alerts.

The programs can be found at these URLs.
bitrigger.zip http://www.cam-it.org/smf/index.php?action=downloads;sa=view;down=1
bicommand1.1.zip http://www.cam-it.org/smf/index.php?action=downloads;sa=view;down=3

Note that bitrigger and bicommand are different programs. As far as I can see bitrigger takes a single parameter such as "cam1" to trigger a camera. Bicommand can do a lot more as shown above.
Also note these programs need to be executed from the same directory as BI.

C#

My aim is to access the DDE server using my own code written in c#.
As a starting point I'm using code from this site http://ndde.codeplex.com/releases/view/4828
It is fairly old code written in the net2.0 days but it seems to compile fine in sharpDevelop-V3
This is a shared source license - Copyright © 2005-2006 by Brian Gideon.


I have never used DDE before and have no desire to become an expert. I'll just stumble around making random changes till I get it to work.

The demos seem to run fine but I haven't managed to get BI to accept my commands yet.
It took a while to locate the basic information required. There doesn't seem to be a complete BI DDE command set in one place anywhere. The commands listed above are enough for my needs.

To connect to the server you have to know the server name which is "blueiris". You also need to have a "topic" parameter - this is "camera".

I can connect OK.

To send command to the server you use a "poke" method and this is failing at the moment.

Debugging.

Oct 23'rd.
It seems the DDE conversation needs to be quite different to what I thought. In order to see what "bicommand" is sending to the DDE server I renamed the demo server in Ndde to "blueiris" and watched the messages.
For the command "bicommand yellow" I didn't see "poke blueiris camera yellow" as I expected.
Instead I saw this...

OnBeforeConnect: Service='blueiris' Topic='camera'
OnAfterConnect:  Service='blueiris' Topic='camera' Handle=33555712
OnDisconnect:    Service='blueiris' Topic='camera' Handle=33555712
OnBeforeConnect: Service='blueiris' Topic='global'
OnAfterConnect:  Service='blueiris' Topic='global' Handle=50332928
OnPoke:          Service='blueiris' Topic='global' Handle=50332928 Item='signal' Data=2 Format=1
OnDisconnect:    Service='blueiris' Topic='global' Handle=50332928

The command "bitrigger cam1" gives this.

OnBeforeConnect: Service='blueiris' Topic='camera'
OnAfterConnect:  Service='blueiris' Topic='camera' Handle=83887360
OnPoke:          Service='blueiris' Topic='camera' Handle=83887360 Item='cam1' Data=8 Format=1
OnDisconnect:    Service='blueiris' Topic='camera' Handle=83887360


"bitrigger cam1" and "bicommand trigger cam1" produce the same DDE conversation.

A few minutes later - success!

OnBeforeConnect: Service='blueiris' Topic='global'
OnAfterConnect:  Service='blueiris' Topic='global' Handle=134222080
OnPoke:          Service='blueiris' Topic='global' Handle=134222080 Item='signal' Data=2 Format=1

After modifying my code to send this(above) when I hit my "yellow" buttom - blue iris accepted the command and changed to signal.
I'm still working on getting the disconnect part right. It does disconnect when my program closes so this may not even be an issue.

The above success is in part a fluke. I wasn't seeing the whole (or correct) message.
I get a data field equal to "2" regardless of what I try to send. However the code works properly when talk to the genuine blueiris server.
(later) It appears the data value dumped by the server is really the data length. Presumably the length includes a terminator, otherwise you'd expect it to be "1" not "2".

The code fragment to connect to the server is.

private DdeClient globalclient;
        public MainForm()
        {
            InitializeComponent();
		    globalclient = new DdeClient("blueiris", "global", this); //  client = new DdeClient("blueiris", "camera", this);
        	globalclient.Disconnected += client_Disconnected; 
        }

To send a yellow signal I do this.

        void Button1Click(object sender, EventArgs e)
        {

        	try
            {
        	globalclient.Poke("signal","2",60000);
        	}
        	catch (Exception ex)
            {
                displayTextBox.Text = "MainForm_Load: " + ex.Message;
            }

        }


To do a "red" command, one line is changed to - globalclient.Poke("signal","0",60000);
For "green" - globalclient.Poke("signal","2",60000);
BTW - the 60000 is a timeout value in milliseconds.

To trigger cam1 - cameraclient.Poke("cam1","trigger",60000);
Note I'm using cameraclient here. I connect both cameraclient and globalclient for the entire session.

As you might expect to do camera 1 snapshot is.
cameraclient.Poke("cam1","snapshot",60000);