Subversion Repositories alarming

Rev

Rev 2 | Rev 9 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 7
Line 1... Line 1...
1
unit DoorAlarmClientMain;
1
unit DoorAlarmClientMain;
2
 
2
 
3
// TODO: make configurable, which actions should be executed (e.g. run programs) when a motion was detected
3
// TODO: make configurable, which actions should be executed (e.g. run programs) when a motion was detected, with different event sounds etc
-
 
4
// TODO: ask server to subscribe/unsubscribe to events (doorbell, motion)
4
 
5
 
5
interface
6
interface
6
 
7
 
7
uses
8
uses
8
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
9
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
9
  Dialogs, HTTPApp, StdCtrls,
10
  Dialogs, HTTPApp, StdCtrls,
10
  IdHTTPServer, idContext, idCustomHTTPServer, OleCtrls, SHDocVw, ExtCtrls,
11
  IdHTTPServer, idContext, idCustomHTTPServer, OleCtrls, SHDocVw, ExtCtrls,
11
  JPEG, MJPEGDecoderUnit, IniFiles, Menus;
12
  JPEG, MJPEGDecoderUnit, IniFiles, Menus;
12
 
13
 
13
type
14
type
-
 
15
  TAlarmType = (atUnknown, atMotion, atDoorbell);
-
 
16
 
14
  TForm1 = class(TForm)
17
  TForm1 = class(TForm)
15
    Image1: TImage;
18
    Image1: TImage;
16
    TrayIcon1: TTrayIcon;
19
    TrayIcon1: TTrayIcon;
17
    PopupMenu1: TPopupMenu;
20
    PopupMenu1: TPopupMenu;
18
    Exit1: TMenuItem;
21
    Exit1: TMenuItem;
Line 24... Line 27...
24
    N1: TMenuItem;
27
    N1: TMenuItem;
25
    Startalarm1: TMenuItem;
28
    Startalarm1: TMenuItem;
26
    N2: TMenuItem;
29
    N2: TMenuItem;
27
    Stopalarm1: TMenuItem;
30
    Stopalarm1: TMenuItem;
28
    Gotocontrolpanelwebsite1: TMenuItem;
31
    Gotocontrolpanelwebsite1: TMenuItem;
-
 
32
    doorbellPanel: TPanel;
-
 
33
    N3: TMenuItem;
-
 
34
    Ignoredoorbell1: TMenuItem;
-
 
35
    Ignoremotionalert1: TMenuItem;
-
 
36
    unknownAlarm: TPanel;
29
    procedure FormDestroy(Sender: TObject);
37
    procedure FormDestroy(Sender: TObject);
30
    procedure FormCreate(Sender: TObject);
38
    procedure FormCreate(Sender: TObject);
31
    procedure TrayIcon1Click(Sender: TObject);
39
    procedure TrayIcon1Click(Sender: TObject);
32
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
40
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
33
    procedure Exit1Click(Sender: TObject);
41
    procedure Exit1Click(Sender: TObject);
Line 50... Line 58...
50
    procedure MotionDetected;
58
    procedure MotionDetected;
51
    procedure HandleFrame(Sender: TObject; Frame: TJPEGImage);
59
    procedure HandleFrame(Sender: TObject; Frame: TJPEGImage);
52
    procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
60
    procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
53
    procedure StartStream;
61
    procedure StartStream;
54
    procedure StopStream;
62
    procedure StopStream;
55
    procedure DoShowForm;
63
    procedure DoShowForm(AlarmType: TAlarmType);
56
    procedure DoPosition;
64
    procedure DoPosition;
57
    procedure StopMusic;
65
    procedure StopMusic;
58
    function ControlServerUrl: string;
66
    function ControlServerUrl: string;
59
  end;
67
  end;
60
 
68
 
Line 267... Line 275...
267
 
275
 
268
  MJPEGDecoder := TMJPEGDecoder.Create(Self);
276
  MJPEGDecoder := TMJPEGDecoder.Create(Self);
269
 
277
 
270
  DoPosition;
278
  DoPosition;
271
 
279
 
-
 
280
  // Question: Should these settings also be saved for the next program session?
272
  Allowmutingsoundinterface1.Checked := ini.ReadBool('Client', 'AllowMute', false);
281
  Allowmutingsoundinterface1.Checked := ini.ReadBool('Client', 'AllowMute', false);
-
 
282
  Ignoredoorbell1.Checked := ini.ReadBool('Client', 'IgnoreDoorbell', false);
-
 
283
  Ignoremotionalert1.Checked := ini.ReadBool('Client', 'IgnoreMotion', false);
273
 
284
 
274
  UpdateIPTimerTimer(UpdateIPTimer);
285
  UpdateIPTimerTimer(UpdateIPTimer);
275
  UpdateIPTimer.Interval := ini.ReadInteger('Client', 'SubscribeInterval', 30*60) * 1000;
286
  UpdateIPTimer.Interval := ini.ReadInteger('Client', 'SubscribeInterval', 30*60) * 1000;
276
  UpdateIPTimer.Enabled := true;
287
  UpdateIPTimer.Enabled := true;
277
end;
288
end;
Line 286... Line 297...
286
  FreeAndNil(MJPEGDecoder);
297
  FreeAndNil(MJPEGDecoder);
287
end;
298
end;
288
 
299
 
289
procedure TForm1.FormHide(Sender: TObject);
300
procedure TForm1.FormHide(Sender: TObject);
290
begin
301
begin
-
 
302
  if Image2.Visible then
291
  StopStream;
303
    StopStream;
292
end;
304
end;
293
 
305
 
294
procedure TForm1.FormShow(Sender: TObject);
306
procedure TForm1.FormShow(Sender: TObject);
295
begin
307
begin
-
 
308
  if Image2.Visible then
296
  StartStream;
309
    StartStream;
297
end;
310
end;
298
 
311
 
299
procedure TForm1.Gotocontrolpanelwebsite1Click(Sender: TObject);
312
procedure TForm1.Gotocontrolpanelwebsite1Click(Sender: TObject);
300
begin
313
begin
Line 307... Line 320...
307
end;
320
end;
308
 
321
 
309
procedure TForm1.ServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
322
procedure TForm1.ServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
310
var
323
var
311
  AutoCloseTimerInterval: integer;
324
  AutoCloseTimerInterval: integer;
-
 
325
  AlarmType: TAlarmType;
312
begin
326
begin
313
  aResponseInfo.ResponseNo  := 200;
327
  aResponseInfo.ResponseNo  := 200;
314
  aResponseInfo.ContentType := 'text/html';
328
  aResponseInfo.ContentType := 'text/html';
315
  aResponseInfo.ContentText := '';
329
  aResponseInfo.ContentText := '';
316
 
330
 
Line 341... Line 355...
341
      begin
355
      begin
342
        CloseTimer.Interval := AutoCloseTimerInterval;
356
        CloseTimer.Interval := AutoCloseTimerInterval;
343
        CloseTimer.Enabled := true;
357
        CloseTimer.Enabled := true;
344
      end;
358
      end;
345
 
359
 
-
 
360
      if ARequestInfo.Params.IndexOf('targets=1.3.6.1.4.1.37476.2.4.2.1002' {camera, motion}) >= 0 then
-
 
361
        AlarmType := atMotion
-
 
362
      else if ARequestInfo.Params.IndexOf('targets=1.3.6.1.4.1.37476.2.4.2.2001' {sound, doorbell}) >= 0 then
-
 
363
        AlarmType := atDoorbell
-
 
364
      else
-
 
365
      begin
-
 
366
        // TODO: Make plugin DLLs ?
-
 
367
        AlarmType := atUnknown;
-
 
368
      end;
-
 
369
 
-
 
370
      // Attention: Ignoring these events at the client does not prevent the server
-
 
371
      // doing other actions (e.g. ask Spotify to stop the music on connected devices)
-
 
372
      if Ignoredoorbell1.Checked and (AlarmType = atDoorbell) then Exit;
-
 
373
      if Ignoremotionalert1.Checked and (AlarmType = atMotion) then Exit;
-
 
374
 
-
 
375
      if AlarmType = atUnknown then
-
 
376
      begin
-
 
377
        unknownAlarm.ShowHint := true;
-
 
378
        unknownAlarm.Hint := ARequestInfo.Params.Text;
-
 
379
      end;
346
      DoShowForm;
380
      DoShowForm(AlarmType);
347
 
381
 
348
      if ini.ReadBool('Client', 'AutoPopup', true) then
382
      if ini.ReadBool('Client', 'AutoPopup', true) then
349
      begin
383
      begin
350
        Application.Restore;
384
        Application.Restore;
351
        WindowState := wsNormal;
385
        WindowState := wsNormal;
Line 367... Line 401...
367
begin
401
begin
368
  // TODO: when clicked, the icon-selection won't close
402
  // TODO: when clicked, the icon-selection won't close
369
  Application.Restore;
403
  Application.Restore;
370
  WindowState := wsNormal;
404
  WindowState := wsNormal;
371
  FormStyle := fsNormal;
405
  FormStyle := fsNormal;
372
  DoShowForm;
406
  DoShowForm(atMotion);
373
end;
407
end;
374
 
408
 
375
procedure TForm1.UpdateIPTimerTimer(Sender: TObject);
409
procedure TForm1.UpdateIPTimerTimer(Sender: TObject);
376
var
410
var
377
  lParamList: TStringList;
411
  lParamList: TStringList;
Line 383... Line 417...
383
      lParamList.Add('action=client_subscribe'); // 1.3.6.1.4.1.37476.2.4.1.1
417
      lParamList.Add('action=client_subscribe'); // 1.3.6.1.4.1.37476.2.4.1.1
384
      lParamList.Add('port='+ini.ReadString('Client', 'ListenPort', ''));
418
      lParamList.Add('port='+ini.ReadString('Client', 'ListenPort', ''));
385
      lParamList.Add('ttl='+IntToStr((UpdateIPTimer.Interval div 1000) * 2 + 10));
419
      lParamList.Add('ttl='+IntToStr((UpdateIPTimer.Interval div 1000) * 2 + 10));
386
      lParamList.Add('targets=1.3.6.1.4.1.37476.2.4.2.0');    // Any
420
      lParamList.Add('targets=1.3.6.1.4.1.37476.2.4.2.0');    // Any
387
      lParamList.Add('targets=1.3.6.1.4.1.37476.2.4.2.1002'); // Motion, camera
421
      lParamList.Add('targets=1.3.6.1.4.1.37476.2.4.2.1002'); // Motion, camera
-
 
422
      lParamList.Add('targets=1.3.6.1.4.1.37476.2.4.2.2001'); // Sound, doorbell
388
 
423
 
389
      idhttp := TIdHTTP.Create(nil);
424
      idhttp := TIdHTTP.Create(nil);
390
      try
425
      try
391
        idhttp.Post(ControlServerUrl, lParamList);
426
        idhttp.Post(ControlServerUrl, lParamList);
392
      finally
427
      finally
Line 425... Line 460...
425
  // TODO: user should select in which corner the window show be
460
  // TODO: user should select in which corner the window show be
426
  Self.Left := Screen.Width - Self.Width;
461
  Self.Left := Screen.Width - Self.Width;
427
  Self.Top := Screen.Height - Self.Height - _TaskBarHeight;
462
  Self.Top := Screen.Height - Self.Height - _TaskBarHeight;
428
end;
463
end;
429
 
464
 
430
procedure TForm1.DoShowForm;
465
procedure TForm1.DoShowForm(AlarmType: TAlarmType);
431
begin
466
begin
-
 
467
  Image1.Visible := AlarmType = atMotion;
-
 
468
  Image2.Visible := AlarmType = atMotion;
-
 
469
 
-
 
470
  // BUGBUG! TODO: This does not work. The panels are not visible for some reason! I just get a white window!
-
 
471
  doorbellPanel.Visible := AlarmType = atDoorbell;
-
 
472
  unknownAlarm.Visible := AlarmType = atUnknown;
-
 
473
 
432
  if ini.ReadBool('Client', 'AutoReposition', true) then
474
  if ini.ReadBool('Client', 'AutoReposition', true) then
433
  begin
475
  begin
434
    DoPosition;
476
    DoPosition;
435
  end;
477
  end;
436
 
478