├── .gitattributes
├── .gitignore
├── DBNewMotionFrames.mdf
├── DBNewMotionFrames_log.ldf
├── OnGuardCore.csproj
├── OnGuardCore.sln
├── OnGuardV2.csproj
├── README.md
├── Resources
├── HelpFiles
│ ├── AddCameraHelp.rtf
│ ├── CameraAddressHelp.rtf
│ ├── CameraTriggeredHelp.rtf
│ ├── DataFilesHelp.rtf
│ ├── FolderPrefixHelp.rtf
│ ├── ISpySnapshotHelp.rtf
│ ├── MMSHelperHelp.rtf
│ ├── ONVIFSnapshotHelp.rtf
│ ├── OnGuardCaptureHelp.rtf
│ ├── OnGuardMonitorHelp.rtf
│ ├── PTZHelp.rtf
│ ├── PTZMovementHelp.rtf
│ ├── PresetsHelp.rtf
│ ├── SnapshotMethodHelp.rtf
│ └── SnapshotResolutionHelp.rtf
├── OnGuard.jpg
├── OnGuardNoPictures.jpg
├── Street1.jpg
├── Street2.jpg
├── Street3.jpg
├── Street4.jpg
├── Street5.jpg
├── Street6.jpg
└── Street7.jpg
├── Setup
└── Setup.vdproj
├── docs
└── OnGuard-ReadMe.docx
├── obj
└── Release
│ └── net5.0-windows
│ ├── Msix
│ └── OnGuard.deps.json
│ ├── OnGuardCore.ZoneBox.resources
│ └── ref
│ └── OnGuard.dll
└── src
├── AI.cs
├── AIAnalyzer.cs
├── AIDetection.cs
├── AITimeUpdater.cs
├── AreaNotificationOption.cs
├── AreaOfInterest.cs
├── AreasOfInterestCollection.cs
├── AwaitableQueue.cs
├── BitmapResolution.cs
├── CameraCollection.cs
├── CameraContactData.cs
├── CameraData.cs
├── Controls
├── CameraImage.Designer.cs
├── CameraImage.cs
├── CameraImage.resx
├── EnhancedProgressBar.Designer.cs
├── EnhancedProgressBar.cs
├── EnhancedProgressBar.resx
├── Resizer.cs
├── Resizer.resx
├── TimeLine.Designer.cs
├── TimeLine.cs
├── TimeLine.resx
├── ZoneBox.cs
└── ZoneBox.resx
├── Cooldowns.cs
├── DBConnection.cs
├── Dbg.cs
├── DirectoryMonitor.cs
├── EmailAccumulator.cs
├── EmailAddresses.cs
├── FaceDetection.cs
├── Forms
├── AIAlertDialog.Designer.cs
├── AIAlertDialog.cs
├── AIAlertDialog.resx
├── AboutDialog.Designer.cs
├── AboutDialog.cs
├── AboutDialog.resx
├── AddCameraDialog.Designer.cs
├── AddCameraDialog.cs
├── AddCameraDialog.resx
├── AddEmailDialog.Designer.cs
├── AddEmailDialog.cs
├── AddEmailDialog.resx
├── AddFaceDialog.Designer.cs
├── AddFaceDialog.cs
├── AddFaceDialog.resx
├── AddUrlDialog.Designer.cs
├── AddUrlDialog.cs
├── AddUrlDialog.resx
├── AnalysisSettingsDialog.Designer.cs
├── AnalysisSettingsDialog.cs
├── AnalysisSettingsDialog.resx
├── AutoFindCamera.Designer.cs
├── AutoFindCamera.cs
├── AutoFindCamera.resx
├── BlueIrisSnapshot.Designer.cs
├── BlueIrisSnapshot.cs
├── BlueIrisSnapshot.resx
├── CameraConfigurationDialog.Designer.cs
├── CameraConfigurationDialog.cs
├── CameraConfigurationDialog.resx
├── CleanupDialog.Designer.cs
├── CleanupDialog.cs
├── CleanupDialog.resx
├── CreateAOI.Designer.cs
├── CreateAOI.cs
├── CreateAOI.resx
├── CreateEmailAddressDialog.Designer.cs
├── CreateEmailAddressDialog.cs
├── CreateEmailAddressDialog.resx
├── DisplayMode.Designer.cs
├── DisplayMode.cs
├── DisplayMode.resx
├── EditAreasOfInterest.Designer.cs
├── EditAreasOfInterest.cs
├── EditAreasOfInterest.resx
├── EmailAddressesDialog.Designer.cs
├── EmailAddressesDialog.cs
├── EmailAddressesDialog.resx
├── FaceDefinitionDialog.Designer.cs
├── FaceDefinitionDialog.cs
├── FaceDefinitionDialog.resx
├── FaceName.Designer.cs
├── FaceName.cs
├── FaceName.resx
├── HTTPPresets.Designer.cs
├── HTTPPresets.cs
├── HTTPPresets.resx
├── HTTPptz.Designer.cs
├── HTTPptz.cs
├── HTTPptz.resx
├── HelpBox.Designer.cs
├── HelpBox.cs
├── HelpBox.resx
├── HttpSnapshot.Designer.cs
├── HttpSnapshot.cs
├── HttpSnapshot.resx
├── ISpyPTZ.Designer.cs
├── ISpyPTZ.cs
├── ISpyPTZ.resx
├── ISpySnapshot.Designer.cs
├── ISpySnapshot.cs
├── ISpySnapshot.resx
├── ImageCaptureDialog.Designer.cs
├── ImageCaptureDialog.cs
├── ImageCaptureDialog.resx
├── InitialPictureBehaviorDialog.Designer.cs
├── InitialPictureBehaviorDialog.cs
├── InitialPictureBehaviorDialog.resx
├── InterestingItemsDialog.Designer.cs
├── InterestingItemsDialog.cs
├── InterestingItemsDialog.resx
├── MMS-Helper.Designer.cs
├── MMS-Helper.cs
├── MMS-Helper.resx
├── MQTTSettings.Designer.cs
├── MQTTSettings.cs
├── MQTTSettings.resx
├── MainWindow.Designer.cs
├── MainWindow.cs
├── MainWindow.resx
├── ModelessMessageWindow.Designer.cs
├── ModelessMessageWindow.cs
├── ModelessMessageWindow.resx
├── NotificationOptionsDialog.Designer.cs
├── NotificationOptionsDialog.cs
├── NotificationOptionsDialog.resx
├── ObjectDefinitionDialog.Designer.cs
├── ObjectDefinitionDialog.cs
├── ObjectDefinitionDialog.resx
├── OnGuardDataDialog.Designer.cs
├── OnGuardDataDialog.cs
├── OnGuardDataDialog.resx
├── OnVIFSnapshot.Designer.cs
├── OnVIFSnapshot.cs
├── OnVIFSnapshot.resx
├── OutgoingEmailDialog.Designer.cs
├── OutgoingEmailDialog.cs
├── OutgoingEmailDialog.resx
├── PTZMovement.Designer.cs
├── PTZMovement.cs
├── PTZMovement.resx
├── PictureDateSelect.Designer.cs
├── PictureDateSelect.cs
├── PictureDateSelect.resx
├── ScheduledPreset.Designer.cs
├── ScheduledPreset.cs
├── ScheduledPreset.resx
├── SetLogLevelDialog.Designer.cs
├── SetLogLevelDialog.cs
├── SetLogLevelDialog.resx
├── SettingsDialog.Designer.cs
├── SettingsDialog.cs
├── SettingsDialog.resx
├── StartRestartAI.Designer.cs
├── StartRestartAI.cs
├── StartRestartAI.resx
├── SyncToDatabaseDialog.Designer.cs
├── SyncToDatabaseDialog.cs
├── SyncToDatabaseDialog.resx
├── Test Email Address.Designer.cs
├── Test Email Address.cs
├── Test Email Address.resx
├── TestPIcturesDialog.Designer.cs
├── TestPIcturesDialog.cs
├── TestPIcturesDialog.resx
├── TestPresets.Designer.cs
├── TestPresets.cs
├── TestPresets.resx
├── iSpyPreset.Designer.cs
├── iSpyPreset.cs
└── iSpyPreset.resx
├── FrameAccumulator.cs
├── FrameAnalyzer.cs
├── GlobalData.cs
├── GlobalSuppressions.cs
├── GridDefinition.cs
├── History.cs
├── IStorage.cs
├── ImageObject.cs
├── MQTTPublish.cs
├── MostRecentCollection.cs
├── MotionDatabase.cs
├── ObjectCharacteristics.cs
├── OnGuardScanner.cs
├── OnVIFSupport.cs
├── PendingItem.cs
├── Picture.cs
├── PictureComparer.cs
├── PictureInfo.cs
├── PictureMotionInfo.cs
├── Program.cs
├── Properties
├── Resource.Designer.cs
├── Resource.resx
├── SamplePictureResources.Designer.cs
├── SamplePictureResources.resx
├── Settings.Designer.cs
└── Settings.settings
├── Resources
├── Icons
│ ├── Guardian.ico
│ ├── arrow-down.png
│ ├── arrow-left.png
│ ├── arrow-right.png
│ ├── arrow-up.png
│ ├── zoom-in.png
│ └── zoom-out.png
├── Images
│ ├── OnGuard.jpg
│ └── OnGuardNoPictures.jpg
└── Samples
│ ├── Street1.jpg
│ ├── Street2.jpg
│ ├── Street3.jpg
│ ├── Street4.jpg
│ ├── Street5.jpg
│ ├── Street6.jpg
│ └── Street7.jpg
├── SafeParse.cs
├── Storage.cs
├── SyncToDB.cs
├── TimeTrigger.cs
├── TimerPlus.cs
├── TriggerCamera.cs
├── WaitCursor.cs
└── XMLStorage.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * -crlf
5 | * -text
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/DBNewMotionFrames.mdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/DBNewMotionFrames.mdf
--------------------------------------------------------------------------------
/DBNewMotionFrames_log.ldf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/DBNewMotionFrames_log.ldf
--------------------------------------------------------------------------------
/OnGuardCore.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OnGuardCore", "OnGuardCore.csproj", "{927CF148-F6BB-41EC-BB98-BF61D8CADBF3}"
7 | EndProject
8 | Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Setup", "Setup\Setup.vdproj", "{006F4EC1-F5CF-4442-B9D2-807F48303511}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Release|Any CPU = Release|Any CPU
15 | Release|x64 = Release|x64
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Debug|Any CPU.ActiveCfg = Debug|x64
19 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Debug|Any CPU.Build.0 = Debug|x64
20 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Debug|x64.ActiveCfg = Debug|x64
21 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Debug|x64.Build.0 = Debug|x64
22 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Release|Any CPU.ActiveCfg = Release|x64
23 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Release|Any CPU.Build.0 = Release|x64
24 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Release|x64.ActiveCfg = Release|x64
25 | {927CF148-F6BB-41EC-BB98-BF61D8CADBF3}.Release|x64.Build.0 = Release|x64
26 | {006F4EC1-F5CF-4442-B9D2-807F48303511}.Debug|Any CPU.ActiveCfg = Release
27 | {006F4EC1-F5CF-4442-B9D2-807F48303511}.Debug|x64.ActiveCfg = Debug
28 | {006F4EC1-F5CF-4442-B9D2-807F48303511}.Release|Any CPU.ActiveCfg = Release
29 | {006F4EC1-F5CF-4442-B9D2-807F48303511}.Release|Any CPU.Build.0 = Release
30 | {006F4EC1-F5CF-4442-B9D2-807F48303511}.Release|x64.ActiveCfg = Release
31 | {006F4EC1-F5CF-4442-B9D2-807F48303511}.Release|x64.Build.0 = Release
32 | EndGlobalSection
33 | GlobalSection(SolutionProperties) = preSolution
34 | HideSolutionNode = FALSE
35 | EndGlobalSection
36 | GlobalSection(ExtensibilityGlobals) = postSolution
37 | SolutionGuid = {787AB3AB-A171-4077-9BAF-6F286EC75237}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/OnGuardV2.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net5.0-windows
6 | true
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This application works with almost any IP/network camera and adds artificial intelligence designed to identify security related pictures. More specifically, it uses DeepStack as an AI to intelligently identify objects in still (.jpg) pictures. It allows the user to monitor as many cameras as desired. It allows the user to visually create multiple areas that are of security interest, including the types of objects that are of interest in each area.
2 |
3 | Version 3.0.1 is a significant update to previous versions. The most dramatic difference is that it fully supports any known camera that supports ONVIF or HTTP. On Guard can now obtain and analyze pictures from (1) the camera itself without disk storage (2) messages sent by a camera using FTP, and taking advantage of motion sensing capabilities of the camera (3) Blue Iris or other applications that write motion related still images to disk.
4 |
5 | On Guard 3.0 features
6 |
7 | It is provided free of charge.
8 | ONVIF and HTTP based cameras are fully supported. This should include almost any camera not locked into a manufacturer proprietary system.
9 | Is fully compatible with, but not reliant on Blue Iris.
10 | Supports multiple cameras.
11 | Support for cameras with different resolution and cameras from different manufacturers.
12 | You can design areas of interest (zones) to identify or ignore activity in an area, including overlapping areas.
13 | You can design your areas to be in almost any shape desired (a 64x64 grid on the pictures).
14 | You can choose to base security notifications based on the size of identified objects (how big and how close they are to the camera).
15 | Supports facial recognition.
16 | Optionally manage the start/stop/reset of the DeepStack AI.
17 | Notify any application that can take an action as a result of an HTTP message/request.
18 | Supports IFTTT activation of lights and other smart devices.
19 | Supports MQTT.
20 | Supports email notification of clients with attached pictures. This also includes the ability to send MMS/SMS messages to phones that support it.
21 | Supports Pan/Tilt/Zoom, and move to preset for cameras that support these features.
22 | Tracks pictures with identified items of interest in a database so that you can move only through those pictures if desired.
23 | Provides a timeline scroll bar. You can now use a track bar to scroll to pictures at any desired date/time.
24 | Cleanup old/uninteresting pictures for one or all cameras.
25 | Detailed documentation/instructions are included.
26 | Can display snapshot pictures/video as an aid in defining areas of interest and camera positioning.
27 |
28 | Features Not Supported
29 |
30 | Does NOT store video to disk.
31 | Does NOT playback videos.
32 | While you can play live video (motion .jpg) directly from a camera, this capability is limited (and not smooth).
33 | Does not support many doorbell cameras, and cameras locked into a proprietary camera ecosystem.
34 |
--------------------------------------------------------------------------------
/Resources/OnGuard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/OnGuard.jpg
--------------------------------------------------------------------------------
/Resources/OnGuardNoPictures.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/OnGuardNoPictures.jpg
--------------------------------------------------------------------------------
/Resources/Street1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street1.jpg
--------------------------------------------------------------------------------
/Resources/Street2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street2.jpg
--------------------------------------------------------------------------------
/Resources/Street3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street3.jpg
--------------------------------------------------------------------------------
/Resources/Street4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street4.jpg
--------------------------------------------------------------------------------
/Resources/Street5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street5.jpg
--------------------------------------------------------------------------------
/Resources/Street6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street6.jpg
--------------------------------------------------------------------------------
/Resources/Street7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/Resources/Street7.jpg
--------------------------------------------------------------------------------
/docs/OnGuard-ReadMe.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/docs/OnGuard-ReadMe.docx
--------------------------------------------------------------------------------
/obj/Release/net5.0-windows/OnGuardCore.ZoneBox.resources:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/obj/Release/net5.0-windows/OnGuardCore.ZoneBox.resources
--------------------------------------------------------------------------------
/obj/Release/net5.0-windows/ref/OnGuard.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/obj/Release/net5.0-windows/ref/OnGuard.dll
--------------------------------------------------------------------------------
/src/AITimeUpdater.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace OnGuardCore
8 | {
9 | public static class AITimeUpdater
10 | {
11 | public delegate void AIProcessTimeDelegate(TimeSpan timespan);
12 | public static event AIProcessTimeDelegate OnAITimeUpdate = delegate {};
13 | public static event AIProcessTimeDelegate OnFrameTimeUpdate = delegate { };
14 |
15 | public static void UpdateFrameTime(TimeSpan span)
16 | {
17 | OnFrameTimeUpdate(span);
18 | }
19 |
20 | public static void UpdateAITime(TimeSpan span)
21 | {
22 | OnAITimeUpdate(span);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/AwaitableQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Runtime.CompilerServices;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.VisualStudio.Threading;
9 |
10 | namespace OnGuardCore
11 | {
12 |
13 | public class AwaitableQueue : IDisposable
14 | {
15 | int _waitTime;
16 | bool _stop;
17 |
18 | ConcurrentQueue _q = new ();
19 | AsyncAutoResetEvent _available = new (true);
20 | private bool disposedValue;
21 |
22 | public AwaitableQueue(int waitTimeInSeconds)
23 | {
24 | _waitTime = waitTimeInSeconds; // 0 - no timeout
25 | }
26 |
27 | public void Add(T addIt)
28 | {
29 | _q.Enqueue(addIt);
30 | _available.Set();
31 | }
32 |
33 | public async Task GetAsync()
34 | {
35 | T result = default;
36 |
37 | while (!_stop)
38 | {
39 | if (_q.TryDequeue(out result))
40 | {
41 | break;
42 | }
43 | else
44 | {
45 | CancellationTokenSource source = new ();
46 | if (_waitTime > 0)
47 | {
48 | source.CancelAfter(_waitTime * 1000);
49 | }
50 |
51 | DateTime startAIWaitTime = DateTime.Now;
52 |
53 | CancellationToken token = source.Token;
54 | await _available.WaitAsync(token).ConfigureAwait(true);
55 | if (token.IsCancellationRequested)
56 | {
57 | TimeSpan span = DateTime.Now - startAIWaitTime;
58 | Dbg.Write(LogLevel.Warning, "AIDetection - Timeout trying to get an AI instance with time: " + span.TotalSeconds.ToString());
59 | break;
60 | }
61 | }
62 | }
63 |
64 | return result;
65 | }
66 |
67 | protected virtual void Dispose(bool disposing)
68 | {
69 | if (!disposedValue)
70 | {
71 | if (disposing)
72 | {
73 | _stop = true;
74 | _available.Set();
75 | }
76 | disposedValue = true;
77 | }
78 | }
79 |
80 | public void Dispose()
81 | {
82 | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
83 | Dispose(disposing: true);
84 | GC.SuppressFinalize(this);
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/BitmapResolution.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace OnGuardCore
10 | {
11 |
12 | ///
13 | /// Just a class to hold a global that has the resolution of the source bitmap
14 | /// We need to access it from multiple files.
15 | ///
16 | public static class BitmapResolution
17 | {
18 | static public int XResolution { get; set; } = 1024;
19 | static public int YResolution { get; set; } = 768;
20 | static public double XScale { get; set; } = 1.0;
21 | static public double YScale { get; set; } = 1.0;
22 |
23 | public static Rectangle ScaleScreenToData(Rectangle rect)
24 | {
25 | Rectangle result = new Rectangle((int)Math.Round(rect.X * XScale), (int)Math.Round(rect.Y * YScale), (int)Math.Round(rect.Width * XScale), (int)Math.Round(rect.Height * YScale));
26 | return result;
27 | }
28 |
29 | public static Point ScaleScreenToData(Point point)
30 | {
31 | Point result = new Point((int)Math.Round(point.X * XScale), (int)Math.Round(point.Y * YScale));
32 | return result;
33 | }
34 |
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/Controls/CameraImage.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace OnGuardCore
3 | {
4 | partial class CameraImage
5 | {
6 | ///
7 | /// Required designer variable.
8 | ///
9 | private System.ComponentModel.IContainer components = null;
10 |
11 | ///
12 | /// Clean up any resources being used.
13 | ///
14 | /// true if managed resources should be disposed; otherwise, false.
15 | protected override void Dispose(bool disposing)
16 | {
17 | if (disposing && (components != null))
18 | {
19 | components.Dispose();
20 | }
21 | base.Dispose(disposing);
22 | }
23 |
24 | #region Component Designer generated code
25 |
26 | ///
27 | /// Required method for Designer support - do not modify
28 | /// the contents of this method with the code editor.
29 | ///
30 | private void InitializeComponent()
31 | {
32 | components = new System.ComponentModel.Container();
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Controls/CameraImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Threading;
10 | using System.Windows.Forms;
11 |
12 | namespace OnGuardCore
13 | {
14 | public partial class CameraImage : PictureBox
15 | {
16 | private object _lock = new object();
17 |
18 | internal int WS_EX_TRANSPARENT = 0x00000020;
19 | Color _color = Color.FromArgb(80, Color.DarkOrange);
20 |
21 | private List _grids;
22 | public CameraImage()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | public void SetImage(Bitmap bitmap)
28 | {
29 | Bitmap oldBitmap = (Bitmap)Image; // can't dispose until we have set the new one
30 | this.Image = new Bitmap(bitmap);
31 | oldBitmap?.Dispose();
32 | }
33 |
34 | public List GridsSelected
35 | {
36 | get
37 | {
38 | lock (_lock)
39 | {
40 | return _grids;
41 | }
42 | }
43 | set
44 | {
45 | lock (_lock)
46 | {
47 | _grids = value;
48 | }
49 | }
50 | }
51 |
52 |
53 | protected override void OnPaint(PaintEventArgs pe)
54 | {
55 | try
56 | {
57 |
58 | // _semaphore.Wait();
59 | base.OnPaint(pe);
60 |
61 | if (GridsSelected != null && GridsSelected.Count > 0)
62 | {
63 | double xSpan = (double) this.Width / (double)GridsSelected[0].XDim;
64 | double ySpan = (double) this.Height / (double) GridsSelected[0].YDim;
65 |
66 | using (SolidBrush brush = new SolidBrush(_color))
67 | {
68 | foreach (var grid in GridsSelected)
69 | {
70 | for (int row = 0; row < grid.YDim; row++)
71 | {
72 | for (int col = 0; col < grid.XDim; col++)
73 | {
74 | if (grid.Get(col, row))
75 | {
76 | pe.Graphics.FillRectangle(brush, (int) Math.Round(col * xSpan), (int) Math.Round(row * ySpan), (int) xSpan + 1, (int) ySpan + 1);
77 | }
78 | }
79 | }
80 | }
81 | }
82 | }
83 | }
84 | finally
85 | {
86 | //_semaphore.Release();
87 | }
88 | }
89 |
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/Controls/EnhancedProgressBar.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace OnGuardCore
3 | {
4 | partial class EnhancedProgressBar
5 | {
6 | ///
7 | /// Required designer variable.
8 | ///
9 | private System.ComponentModel.IContainer components = null;
10 |
11 | ///
12 | /// Clean up any resources being used.
13 | ///
14 | /// true if managed resources should be disposed; otherwise, false.
15 | protected override void Dispose(bool disposing)
16 | {
17 | if (disposing && (components != null))
18 | {
19 | components.Dispose();
20 | }
21 | base.Dispose(disposing);
22 | }
23 |
24 | #region Component Designer generated code
25 |
26 | ///
27 | /// Required method for Designer support - do not modify
28 | /// the contents of this method with the code editor.
29 | ///
30 | private void InitializeComponent()
31 | {
32 | this.SuspendLayout();
33 | //
34 | // UserControl1
35 | //
36 | this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
37 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
38 | this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
39 | this.Name = "UserControl1";
40 | this.Size = new System.Drawing.Size(187, 22);
41 | this.ResumeLayout(false);
42 |
43 | }
44 |
45 | #endregion
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Controls/EnhancedProgressBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Drawing.Drawing2D;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 |
12 | namespace OnGuardCore
13 | {
14 | public partial class EnhancedProgressBar : UserControl
15 | {
16 | SolidBrush eraseBrush;
17 | public EnhancedProgressBar()
18 | {
19 | InitializeComponent();
20 | eraseBrush = new SolidBrush(this.BackColor);
21 |
22 | }
23 |
24 | public void SetContents(Color color, double percent, string text)
25 | {
26 | using (Graphics g = this.CreateGraphics())
27 | {
28 | Rectangle clientRect = this.ClientRectangle;
29 | g.FillRectangle(eraseBrush, clientRect);
30 |
31 | using (SolidBrush barBrush = new SolidBrush(color))
32 | {
33 | Rectangle barRect = clientRect;
34 | barRect.Width = (int)((double)clientRect.Width * percent / 100.0);
35 | g.FillRectangle(barBrush, barRect);
36 |
37 | g.SmoothingMode = SmoothingMode.AntiAlias;
38 | g.InterpolationMode = InterpolationMode.HighQualityBicubic;
39 | g.PixelOffsetMode = PixelOffsetMode.HighQuality;
40 |
41 | using (Font f = new Font("Tahoma", 8, FontStyle.Bold))
42 | {
43 | SizeF stringWidth = g.MeasureString(text, f);
44 | int left = clientRect.Width / 2 - (int) stringWidth.Width / 2;
45 | Rectangle textRect = clientRect;
46 | textRect.X = left;
47 | g.DrawString(text, f, Brushes.Black, textRect);
48 | }
49 | }
50 |
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Controls/TimeLine.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Windows.Forms;
3 |
4 | namespace OnGuardCore
5 | {
6 | partial class TimeLine : TrackBar
7 | {
8 | ///
9 | /// Required designer variable.
10 | ///
11 | private System.ComponentModel.IContainer components = null;
12 |
13 | ///
14 | /// Clean up any resources being used.
15 | ///
16 | /// true if managed resources should be disposed; otherwise, false.
17 | protected override void Dispose(bool disposing)
18 | {
19 | if (disposing && (components != null))
20 | {
21 | components.Dispose();
22 | }
23 | base.Dispose(disposing);
24 | }
25 |
26 | #region Component Designer generated code
27 |
28 | ///
29 | /// Required method for Designer support - do not modify
30 | /// the contents of this method with the code editor.
31 | ///
32 | private void InitializeComponent()
33 | {
34 | components = new System.ComponentModel.Container();
35 | }
36 |
37 | #endregion
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Controls/ZoneBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Windows.Forms;
4 |
5 | namespace OnGuardCore
6 | {
7 |
8 | public class ZoneBox : Panel
9 | {
10 | internal int WS_EX_TRANSPARENT = 0x00000020;
11 | Color _color;
12 | readonly Color _focusColor = Color.FromArgb(200, Color.MediumAquamarine);
13 | Rectangle _focusRect = Rectangle.Empty;
14 | Point _focusPoint = Point.Empty;
15 |
16 | public Point ZoneFocus
17 | {
18 | get
19 | {
20 | return _focusPoint;
21 | }
22 | set
23 | {
24 | _focusPoint = value;
25 | _focusRect = new Rectangle(ZoneFocus.X - 5, ZoneFocus.Y - 5, 10, 10);
26 | }
27 | }
28 |
29 | public ZoneBox(Color color) : base()
30 | {
31 | _color = color;
32 |
33 | InitializeComponent();
34 | this.SetStyle(ControlStyles.Opaque |
35 | ControlStyles.ResizeRedraw |
36 | ControlStyles.SupportsTransparentBackColor, true);
37 | this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
38 | this.BorderStyle = BorderStyle.None;
39 |
40 | BringToFront();
41 | }
42 |
43 | protected override CreateParams CreateParams
44 | {
45 | get
46 | {
47 | CreateParams parameters = base.CreateParams;
48 | parameters.ExStyle |= WS_EX_TRANSPARENT;
49 | return parameters;
50 | }
51 | }
52 |
53 | protected override void OnLocationChanged(EventArgs e)
54 | {
55 | Parent.Invalidate();
56 | Invalidate();
57 | }
58 |
59 | protected override void OnPaint(PaintEventArgs e)
60 | {
61 | //base.OnPaint(e);
62 | e.Graphics.SetClip(new Rectangle(0, 0, Width, Height));
63 | using (SolidBrush brush = new SolidBrush(_color))
64 | {
65 | e.Graphics.FillRectangle(brush, 0, 0, this.Width + 1, this.Height + 1);
66 | if (_focusRect != Rectangle.Empty)
67 | {
68 | using (SolidBrush focusBrush = new SolidBrush(_focusColor))
69 | {
70 | e.Graphics.FillRectangle(focusBrush, _focusRect);
71 | }
72 | }
73 | }
74 | }
75 |
76 | protected override void OnPaintBackground(PaintEventArgs e)
77 | {
78 | e.Graphics.SetClip(new Rectangle(0, 0, Width, Height));
79 | using (SolidBrush brush = new SolidBrush(_color))
80 | {
81 | e.Graphics.FillRectangle(brush, 0, 0, this.Width + 1, this.Height + 1);
82 | }
83 | }
84 |
85 | private void InitializeComponent()
86 | {
87 | this.SuspendLayout();
88 | //
89 | // ZoneBox
90 | //
91 | this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown);
92 | this.ResumeLayout(false);
93 |
94 | }
95 |
96 | private void OnMouseDown(object sender, MouseEventArgs e)
97 | {
98 | if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
99 | {
100 | _focusRect = BitmapResolution.ScaleScreenToData(new Rectangle(e.X - 5, e.Y - 5, 10, 10));
101 | ZoneFocus = e.Location;
102 | }
103 |
104 | Parent.Invalidate();
105 | this.Invalidate();
106 | }
107 |
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/DBConnection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using OnGuardCore.Src.Properties;
8 |
9 | namespace OnGuardCore
10 | {
11 | public static class DBConnection
12 | {
13 | ///
14 | /// Get either the custom connection string or the default one.
15 | ///
16 | ///
17 | public static string GetConnectionString()
18 | {
19 | string connectionString = string.Empty;
20 | connectionString = Storage.Instance.GetGlobalString("CustomDatabaseConnectionString");
21 |
22 | if (string.IsNullOrEmpty(connectionString))
23 | {
24 | // This the normal case where there is no custom string
25 | connectionString = GetDefaultConnectionString();
26 |
27 | /*
28 | string currentString = Storage.Instance.GetGlobalString("DBConnectionString");
29 | connectionString = GetDefaultConnectionString();
30 | if (currentString != connectionString)
31 | {
32 | Dbg.Write("DBConnection - GetConnectionString - Unexpected location difference");
33 | Storage.Instance.SetGlobalString("DBConnectionString", connectionString);
34 | Storage.Instance.Update();
35 | }
36 | */
37 | }
38 |
39 | return connectionString;
40 | }
41 |
42 | ///
43 | /// Store the path (only) to the database
44 | ///
45 | ///
46 | public static void SetDatabasePath(string path)
47 | {
48 | Storage.Instance.SetGlobalString("DatabasePath", path);
49 | Storage.Instance.Update();
50 | }
51 |
52 | public static string GetDatabasePath()
53 | {
54 | string path = Storage.Instance.GetGlobalString("DatabasePath");
55 | if (string.IsNullOrEmpty(path))
56 | {
57 | path = Settings.Default.DataFileLocation;
58 | Storage.Instance.SetGlobalInt("DBLocationType", 0); // the user directory
59 | }
60 |
61 | return path;
62 | }
63 |
64 | ///
65 | /// The settings connection string is the minimal connection string without a path. Instead it has a {0] for the path that is then filled in here.
66 | /// If we have already set the database path in the xml file we use that. Otherwise we use the user directory where the installer should have
67 | /// put the database.
68 | /// No luck using |DataDirectory
69 | ///
70 | ///
71 | public static string GetDefaultConnectionString()
72 | {
73 | // Since we are getting the value we need to format it
74 | string baseConnectionString = Settings.Default.DBMotionFramesConnectionString; // the base string with {0} in place of the file location
75 | string dbLocation = GetDatabasePath();
76 | string connectionString = string.Format(baseConnectionString, dbLocation); // insert the localdb path
77 | return connectionString;
78 | }
79 |
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/EmailAddresses.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Runtime.Serialization.Formatters.Binary;
5 |
6 | namespace OnGuardCore
7 | {
8 | ///
9 | /// Just a wrapper that holds a list of the available email addresses (along with the related time/dow restrictions
10 | /// Provides a wrapper for persistence.
11 | ///
12 | [Serializable]
13 | public sealed class EmailAddresses
14 | {
15 |
16 | public static List EmailAddressList { get; set; }
17 |
18 | static EmailAddresses()
19 | {
20 | EmailAddressList = new List();
21 | Load();
22 | }
23 |
24 | static public EmailOptions GetEmailOptions(string emailAddress)
25 | {
26 | EmailOptions opt = null;
27 | opt = EmailAddressList.Find(x => emailAddress == x.EmailAddress);
28 | return opt;
29 | }
30 |
31 | public static void Save()
32 | {
33 | Storage.Instance.SaveEmailAddresses(EmailAddressList);
34 | }
35 |
36 | public static void Load()
37 | {
38 | EmailAddressList = Storage.Instance.GetEmailAddresses();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Forms/AIAlertDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class AIAlertDialog : Form
14 | {
15 | public AIAlertDialog()
16 | {
17 | InitializeComponent();
18 | foreach (var options in EmailAddresses.EmailAddressList)
19 | {
20 | EmailListBox.Items.Add(options.EmailAddress);
21 | }
22 |
23 | string emailRecipient = Storage.Instance.GetGlobalString("NotifyAIGoneEmail");
24 |
25 | if (!string.IsNullOrEmpty(emailRecipient))
26 | {
27 | EmailListBox.SelectedItem = emailRecipient;
28 | }
29 |
30 | string mqttAIDiedTopic = Storage.Instance.GetGlobalString("MQTTaiDiedTopic");
31 | string mqttAIDiedPayload = Storage.Instance.GetGlobalString("MQTTaiDiedPayload");
32 | bool mqttSendAIDied = Storage.Instance.GetGlobalBool("MQTTSendAIDied");
33 |
34 | if (!string.IsNullOrEmpty(mqttAIDiedTopic))
35 | {
36 | AIDiedTopicText.Text = mqttAIDiedTopic;
37 | }
38 |
39 | if (!string.IsNullOrEmpty(mqttAIDiedPayload))
40 | {
41 | AIDiedPayloadText.Text = mqttAIDiedPayload;
42 | }
43 |
44 | sendAIDiedMQTTCheckbox.Checked = mqttSendAIDied;
45 |
46 | }
47 |
48 | private void OKButton_Click(object sender, EventArgs e)
49 | {
50 | if (EmailListBox.SelectedItems.Count > 0)
51 | {
52 | Storage.Instance.SetGlobalString("NotifyAIGoneEmail", (string)EmailListBox.SelectedItem);
53 | }
54 |
55 | Storage.Instance.SetGlobalString("MQTTaiDiedTopic", AIDiedTopicText.Text);
56 | Storage.Instance.SetGlobalString("MQTTaiDiedPayload", AIDiedPayloadText.Text);
57 | Storage.Instance.SetGlobalBool("MQTTSendAIDied", sendAIDiedMQTTCheckbox.Checked);
58 | Storage.Instance.Update();
59 | DialogResult = DialogResult.OK;
60 | }
61 |
62 | private void CancelButton_Click(object sender, EventArgs e)
63 | {
64 | DialogResult = DialogResult.Cancel;
65 | }
66 |
67 | private void RemoveButton_Click(object sender, EventArgs e)
68 | {
69 | EmailListBox.SelectedIndex = -1;
70 | Storage.Instance.RemoveGlobalValue("NotifyAIGoneEmail");
71 | }
72 | }
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/src/Forms/AIAlertDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
61 | When/if your AI server dies OR IS VERY SLOW TO RESPOND (overloaded) you may receive a notification via email and/or MQTT. At the moment this notification is limited to one (and only one) email address.
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/Forms/AboutDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Security.Cryptography.X509Certificates;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 | using System.Reflection;
12 |
13 |
14 | namespace OnGuardCore
15 | {
16 | public partial class AboutDialog : Form
17 | {
18 | public AboutDialog()
19 | {
20 | InitializeComponent();
21 | assemblyLabel.Text = AssemblyVersion;
22 | }
23 |
24 | public static string AssemblyTitle
25 | {
26 | get
27 | {
28 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
29 | if (attributes.Length > 0)
30 | {
31 | AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
32 | if (!string.IsNullOrEmpty(titleAttribute.Title))
33 | {
34 | return titleAttribute.Title;
35 | }
36 | }
37 | return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
38 | }
39 | }
40 |
41 | public static string AssemblyVersion
42 | {
43 | get
44 | {
45 | return Assembly.GetExecutingAssembly().GetName().Version.ToString();
46 | }
47 | }
48 |
49 | public static string AssemblyDescription
50 | {
51 | get
52 | {
53 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
54 | if (attributes.Length == 0)
55 | {
56 | return "";
57 | }
58 | return ((AssemblyDescriptionAttribute)attributes[0]).Description;
59 | }
60 | }
61 |
62 | public static string AssemblyProduct
63 | {
64 | get
65 | {
66 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
67 | if (attributes.Length == 0)
68 | {
69 | return "";
70 | }
71 | return ((AssemblyProductAttribute)attributes[0]).Product;
72 | }
73 | }
74 |
75 | public static string AssemblyCopyright
76 | {
77 | get
78 | {
79 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
80 | if (attributes.Length == 0)
81 | {
82 | return "";
83 | }
84 | return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
85 | }
86 | }
87 |
88 | public static string AssemblyCompany
89 | {
90 | get
91 | {
92 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
93 | if (attributes.Length == 0)
94 | {
95 | return "";
96 | }
97 | return ((AssemblyCompanyAttribute)attributes[0]).Company;
98 | }
99 | }
100 |
101 | private void OKButton_Click(object sender, EventArgs e)
102 | {
103 | DialogResult = DialogResult.OK;
104 | }
105 | }
106 |
107 |
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/src/Forms/AddCameraDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
61 | All image generation methods require that you specify the prefix for picture image names. The remainder on the name must be unique to the individual picture.
62 |
63 | An example is: “aiFrontCamera2012_09_13_4234565.jpg”
64 |
65 |
66 |
--------------------------------------------------------------------------------
/src/Forms/AddEmailDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace OnGuardCore
5 | {
6 |
7 | ///
8 | /// A simple dialog to add email addresses to the AOI notifications dialog
9 | ///
10 | public partial class AddEmailDialog : Form
11 | {
12 | public string EmailAddress { get; set; }
13 | public AddEmailDialog()
14 | {
15 | InitializeComponent();
16 | foreach (var options in EmailAddresses.EmailAddressList)
17 | {
18 | emailAddressList.Items.Add(options.EmailAddress);
19 | }
20 | }
21 |
22 | private void OkButton_Click(object sender, EventArgs e)
23 | {
24 | if (null != emailAddressList.SelectedItem)
25 | {
26 | EmailAddress = (string)emailAddressList.SelectedItem;
27 | DialogResult = DialogResult.OK;
28 | }
29 | else
30 | {
31 | MessageBox.Show("You must select an email address or press Cancel");
32 | }
33 | }
34 |
35 | private void CancelButton_Click(object sender, EventArgs e)
36 | {
37 | DialogResult = DialogResult.Cancel;
38 | }
39 |
40 | private void OnMouseDoubleClick(object sender, MouseEventArgs e)
41 | {
42 | if (null != emailAddressList.SelectedItem)
43 | {
44 | EmailAddress = (string)emailAddressList.SelectedItem;
45 | }
46 | DialogResult = DialogResult.OK;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Forms/AddEmailDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/AddFaceDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 | using System.IO;
11 |
12 |
13 |
14 | namespace OnGuardCore
15 | {
16 | public partial class AddFaceDialog : Form
17 | {
18 |
19 | public string FaceName { get; set; }
20 | public int Confidence { get; set; }
21 |
22 | public AddFaceDialog(FaceID face)
23 | {
24 | InitializeComponent();
25 |
26 | string basePath = Storage.GetFilePath(string.Empty);
27 | basePath = Path.Combine(basePath, "Faces");
28 | if (!Directory.Exists(basePath))
29 | {
30 | Directory.CreateDirectory(basePath);
31 | }
32 |
33 | string[] existingNames = Directory.GetDirectories(basePath);
34 | foreach (string nameDir in existingNames)
35 | {
36 | if (basePath.Length < nameDir.Length)
37 | {
38 | string subDir = nameDir[(basePath.Length + 1)..];
39 | FacesComboBox.Items.Add(subDir);
40 | }
41 | }
42 |
43 | if (FacesComboBox.Items.Count > 0)
44 | {
45 | if (null != face)
46 | {
47 | FacesComboBox.SelectedItem = face.Name;
48 | }
49 | }
50 | }
51 |
52 | private void CancelButton_Click(object sender, EventArgs e)
53 | {
54 | DialogResult = DialogResult.Cancel;
55 | }
56 |
57 | private void OKButton_Click(object sender, EventArgs e)
58 | {
59 | if (FacesComboBox.SelectedIndex != -1)
60 | {
61 | FaceName = (string)FacesComboBox.Items[FacesComboBox.SelectedIndex];
62 | Confidence = (int)ConfidenceNumeric.Value;
63 | DialogResult = DialogResult.OK;
64 | }
65 | }
66 | }
67 |
68 | public class FaceID
69 | {
70 | public string Name { get; set; }
71 | public int Confidence { get; set; }
72 | public bool Selected { get; set; }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/Forms/AddFaceDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/AddUrlDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace OnGuardCore
5 | {
6 |
7 | ///
8 | /// A simple dialog to an an URL with a Cooldown.
9 | /// We could make the URLs global like the email addresses, but not for now
10 | ///
11 | public partial class AddUrlDialog : Form
12 | {
13 |
14 | public UrlOptions Options { get; }
15 |
16 | public AddUrlDialog(UrlOptions options)
17 | {
18 | InitializeComponent();
19 | Options = options;
20 | if (null == options)
21 | {
22 | Options = new UrlOptions(string.Empty, 0, 300, 0);
23 | }
24 | else
25 | {
26 | urlText.Text = Options.Url;
27 | urlCoolDownNumeric.Value = Options.CoolDown.CooldownTime;
28 | WaitTimeNumeric.Value = Options.WaitTime;
29 |
30 | if ((Options.BIFlags & (int) BIFLAGS.Flagged) > 0)
31 | {
32 | FlagCheckBox.Checked = true;
33 | }
34 |
35 | if ((Options.BIFlags & (int) BIFLAGS.Confirmed) > 0)
36 | {
37 | ConfirmCheckBox.Checked = true;
38 | }
39 |
40 | if ((Options.BIFlags & (int) BIFLAGS.Reset) > 0)
41 | {
42 | ResetCheckBox.Checked = true;
43 | }
44 | }
45 |
46 | }
47 |
48 | private void OkButton_Click(object sender, EventArgs e)
49 | {
50 | if (string.IsNullOrEmpty(urlText.Text))
51 | {
52 | MessageBox.Show(this, "You must enter an URL to notify (or we can't get there from here)!", "The URL Cannot be Empty!");
53 | DialogResult = DialogResult.None;
54 | }
55 | else
56 | {
57 | Options.BIFlags = 0;
58 | Options.Url = urlText.Text;
59 | if (FlagCheckBox.Checked) Options.BIFlags |= (int) BIFLAGS.Flagged;
60 | if (ConfirmCheckBox.Checked) Options.BIFlags |= (int) BIFLAGS.Confirmed;
61 | if (ResetCheckBox.Checked) Options.BIFlags |= (int) BIFLAGS.Reset;
62 | Options.CoolDown.CooldownTime = (int) urlCoolDownNumeric.Value;
63 | Options.WaitTime = (int)WaitTimeNumeric.Value;
64 | DialogResult = DialogResult.OK;
65 | }
66 | }
67 |
68 | private void CancelButton_Click(object sender, EventArgs e)
69 | {
70 | DialogResult = DialogResult.Cancel;
71 | }
72 |
73 | private void AutoFillButton_Click(object sender, EventArgs e)
74 | {
75 | urlText.Text = "{Auto Fill}";
76 | }
77 |
78 | private void ConfirmOnCheckChanged(object sender, EventArgs e)
79 | {
80 | }
81 |
82 |
83 | private void FlagCheckChanged(object sender, EventArgs e)
84 | {
85 | }
86 |
87 |
88 | private void ResetCheckBox_CheckedChanged(object sender, EventArgs e)
89 | {
90 | if (ResetCheckBox.Checked)
91 | {
92 | FlagCheckBox.Checked = false;
93 | ConfirmCheckBox.Checked = false;
94 | }
95 | }
96 | }
97 |
98 | [Flags]
99 | public enum BIFLAGS
100 | {
101 | Uncomfirmed = 0,
102 | Flagged = 1,
103 | Confirmed = 2,
104 | Reset = 4
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/src/Forms/AddUrlDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/AnalysisSettingsDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class AnalysisSettingsDialog : Form
14 | {
15 | public AnalysisSettingsDialog()
16 | {
17 | InitializeComponent();
18 | ParkedCarsOverlapCheckbox.Checked = Storage.Instance.GetGlobalBool("ExcludeParkedUsingOverlap", true);
19 | ExcludeParkedCornersCheckbox.Checked = Storage.Instance.GetGlobalBool("ExcludeParkedUsingCorners", true);
20 | BumpVehicleConfidenceCheck.Checked = Storage.Instance.GetGlobalBool("BumpMultiVehicleConfidence", true);
21 | }
22 |
23 | private void OKButton_Click(object sender, EventArgs e)
24 | {
25 | Storage.Instance.SetGlobalBool("ExcludeParkedUsingOverlap", ParkedCarsOverlapCheckbox.Checked);
26 | Storage.Instance.SetGlobalBool("ExcludeParkedUsingCorners", ExcludeParkedCornersCheckbox.Checked);
27 | Storage.Instance.SetGlobalBool("BumpMultiVehicleConfidence", BumpVehicleConfidenceCheck.Checked);
28 | Storage.Instance.Update();
29 | DialogResult = DialogResult.OK;
30 | }
31 |
32 | private void CancelButton_Click(object sender, EventArgs e)
33 | {
34 | DialogResult = DialogResult.Cancel;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Forms/AnalysisSettingsDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/BlueIrisSnapshot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class BlueIrisSnapshot : Form
14 | {
15 | string _shortCameraName;
16 | CameraData _camera;
17 | public string ShortCameraName { get => _shortCameraName; set => _shortCameraName = value; }
18 |
19 | public BlueIrisSnapshot(CameraData camera)
20 | {
21 | _camera = camera;
22 | InitializeComponent();
23 | textBoxCameraName.Text = camera.Contact.CameraShortName;
24 | }
25 |
26 | private void OkButton_Click(object sender, EventArgs e)
27 | {
28 | ShortCameraName = textBoxCameraName.Text;
29 | DialogResult = DialogResult.OK;
30 | }
31 |
32 | private void CancelButton_Click(object sender, EventArgs e)
33 | {
34 | DialogResult = DialogResult.Cancel;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Forms/CleanupDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/CreateAOI.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/DisplayMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class DisplayMode : Form
14 | {
15 | public DisplayOption DisplayType { get; set; }
16 | public DisplayMode(DisplayOption display)
17 | {
18 | InitializeComponent();
19 |
20 | if (display == DisplayOption.FilledHorizontally)
21 | {
22 | HorizontalFillRadio.Checked = true;
23 | }
24 | else if (display == DisplayOption.FilledVertically)
25 | {
26 | VerticalFillRadio.Checked = true;
27 | }
28 | else if (display == DisplayOption.FilledBoth)
29 | {
30 | FilledRadio.Checked = true;
31 | }
32 | else if (display == DisplayOption.Fixed)
33 | {
34 | FixedRadio.Checked = true;
35 | }
36 |
37 | }
38 |
39 | private void OKButton_Click(object sender, EventArgs e)
40 | {
41 | if (HorizontalFillRadio.Checked)
42 | {
43 | DisplayType = DisplayOption.FilledHorizontally;
44 | }
45 | else if (VerticalFillRadio.Checked)
46 | {
47 | DisplayType = DisplayOption.FilledVertically;
48 | }
49 | else if (FilledRadio.Checked)
50 | {
51 | DisplayType = DisplayOption.FilledBoth;
52 | }
53 | else if (FixedRadio.Checked)
54 | {
55 | DisplayType |= DisplayOption.Fixed;
56 | }
57 |
58 | DialogResult = DialogResult.OK;
59 | }
60 |
61 | private void CancelButton_Click(object sender, EventArgs e)
62 | {
63 | DialogResult = DialogResult.Cancel;
64 | }
65 |
66 | private void FilledRadio_CheckedChanged(object sender, EventArgs e)
67 | {
68 |
69 | }
70 | }
71 |
72 | public enum DisplayOption
73 | {
74 | FilledHorizontally,
75 | FilledBoth,
76 | Fixed,
77 | FilledVertically
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Forms/DisplayMode.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/EditAreasOfInterest.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/EmailAddressesDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows.Forms;
4 |
5 | namespace OnGuardCore
6 | {
7 | public partial class EmailAddressesDialog : Form
8 | {
9 | List Options { get; }
10 | public EmailAddressesDialog(List options)
11 | {
12 | InitializeComponent();
13 | Options = options;
14 |
15 | if (options != null)
16 | {
17 | foreach (EmailOptions option in Options)
18 | {
19 | ListViewItem item = emailAddressList.Items.Add(option.EmailAddress);
20 | item.Tag = option;
21 | }
22 | }
23 | }
24 |
25 | private void OKButton_Click(object sender, EventArgs e)
26 | {
27 | Options.Clear();
28 | foreach (ListViewItem item in emailAddressList.Items)
29 | {
30 | Options.Add((EmailOptions)item.Tag);
31 | }
32 |
33 | DialogResult = DialogResult.OK;
34 | }
35 |
36 | private void CancelButton_Click(object sender, EventArgs e)
37 | {
38 | DialogResult = DialogResult.Cancel;
39 | }
40 |
41 | private void AddButton_Click(object sender, EventArgs e)
42 | {
43 | using (CreateEmailAddressDialog dlg = new CreateEmailAddressDialog())
44 | {
45 | DialogResult result = dlg.ShowDialog();
46 | if (result == DialogResult.OK)
47 | {
48 | ListViewItem item = new ListViewItem(dlg.Email.EmailAddress)
49 | {
50 | Tag = dlg.Email
51 | };
52 | emailAddressList.Items.Add(item);
53 | }
54 | }
55 | }
56 |
57 | private void EditButton_Click(object sender, EventArgs e)
58 | {
59 | if (emailAddressList.SelectedIndices.Count > 0)
60 | {
61 | using (CreateEmailAddressDialog dlg = new CreateEmailAddressDialog((EmailOptions)emailAddressList.Items[emailAddressList.SelectedIndices[0]].Tag))
62 | {
63 | DialogResult result = dlg.ShowDialog();
64 | if (result == DialogResult.OK)
65 | {
66 | emailAddressList.Items[emailAddressList.SelectedIndices[0]].Tag = dlg.Email;
67 | }
68 | }
69 | }
70 | }
71 |
72 | private void DeleteButton_Click(object sender, EventArgs e)
73 | {
74 | int index = emailAddressList.SelectedIndices[0];
75 | AddButton.Focus();
76 | emailAddressList.Items.RemoveAt(index);
77 | }
78 |
79 | private void OnSelectedIndexChanged(object sender, EventArgs e)
80 | {
81 | if (emailAddressList.SelectedIndices.Count > 0)
82 | {
83 | EditButton.Enabled = true;
84 | DeleteButton.Enabled = true;
85 | }
86 | else
87 | {
88 | EditButton.Enabled = false;
89 | DeleteButton.Enabled = false;
90 | }
91 | }
92 |
93 | private void OnActivate(object sender, EventArgs e)
94 | {
95 | EditButton_Click(sender, e);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/Forms/EmailAddressesDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/FaceDefinitionDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
61 | Face detection occurs in two stages. First, we identify people in the picture. Second, we pass just the picture(s) for the people to the AI. The AI then attempts to recognize the face(s) (if any). So, in step one we define the basic requirements for identifying people.
62 |
63 |
--------------------------------------------------------------------------------
/src/Forms/FaceName.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 |
12 | namespace OnGuardCore
13 | {
14 | public partial class FaceName : Form
15 | {
16 | public String NameOfPerson { get; set; }
17 | public string Person { get; set; }
18 |
19 | string _basePath;
20 |
21 | public FaceName()
22 | {
23 | InitializeComponent();
24 |
25 | _basePath = Storage.GetFilePath(string.Empty);
26 | _basePath = Path.Combine(_basePath, "Faces");
27 | if (!Directory.Exists(_basePath))
28 | {
29 | Directory.CreateDirectory(_basePath);
30 | }
31 |
32 | string[] existingNames = Directory.GetDirectories(_basePath);
33 | foreach (string nameDir in existingNames)
34 | {
35 | if (_basePath.Length < nameDir.Length)
36 | {
37 | string subDir = nameDir[(_basePath.Length + 1)..];
38 | FacesComboBox.Items.Add(subDir);
39 | }
40 | }
41 |
42 | if (FacesComboBox.Items.Count > 0)
43 | {
44 | FacesComboBox.SelectedIndex = 0;
45 | }
46 |
47 | }
48 |
49 | private void OKButton_Click(object sender, EventArgs e)
50 | {
51 |
52 | string person = string.Empty;
53 | if (FacesComboBox.SelectedIndex != -1)
54 | {
55 | person = (string)FacesComboBox.SelectedItem;
56 | }
57 | else if (!string.IsNullOrEmpty(FacesComboBox.Text))
58 | {
59 | person = (string)FacesComboBox.Text;
60 | }
61 |
62 | if (!string.IsNullOrEmpty(person))
63 | {
64 | string fullPath = Path.Combine(_basePath, person);
65 | if (!Directory.Exists(fullPath))
66 | {
67 | Directory.CreateDirectory(fullPath);
68 | }
69 |
70 | NameOfPerson = Path.Combine(fullPath, person + DateTime.Now.Ticks.ToString() + ".jpg");
71 | Person = person;
72 |
73 | DialogResult = DialogResult.OK;
74 | }
75 | else
76 | {
77 | MessageBox.Show(this, "You must enter the name of the person!", "Name is Invalid!");
78 | }
79 | }
80 |
81 |
82 | private void CancelButton_Click(object sender, EventArgs e)
83 | {
84 | NameOfPerson = string.Empty;
85 | DialogResult = DialogResult.Cancel;
86 | }
87 |
88 | private void AddButton_Click(object sender, EventArgs e)
89 | {
90 | FacesComboBox.Items.Add(FacesComboBox.Text);
91 | Directory.CreateDirectory(Path.Combine(_basePath, FacesComboBox.Text));
92 | FacesComboBox.SelectedItem = FacesComboBox.Text;
93 |
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/Forms/FaceName.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/HTTPPresets.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class HTTPPresets : Form
14 | {
15 | CameraData _camera;
16 | public HTTPPresets(CameraData camera)
17 | {
18 | _camera = camera;
19 | InitializeComponent();
20 |
21 | labelCurrentCamera.Text = "Current Camera: " + _camera.CameraPrefix;
22 | if (camera.Contact.PresetSettings.PresetList.Count > 0)
23 | {
24 | string str = camera.Contact.PresetSettings.PresetList[0].Command;
25 | if (str.Contains("[ADDRESS]")) // It should
26 | {
27 | int offset = str.IndexOf("[ADDRESS]");
28 | offset += "[ADDRESS]".Length;
29 | str = str.Remove(0, offset);
30 | textBoxUrl.Text = str;
31 | }
32 | }
33 | }
34 |
35 |
36 | private void OKButton_Click(object sender, EventArgs e)
37 | {
38 |
39 | if (textBoxUrl.Text.Contains("http") || textBoxUrl.Text.Contains("[ADDRESS]"))
40 | {
41 | MessageBox.Show("Your URL must NOT contain either http or [ADDRESS]. These values will be added automatically", "Invalid URL Format!");
42 | }
43 | else
44 | {
45 |
46 | if (textBoxUrl.Text.Contains("[PRESET]") || textBoxUrl.Text.Contains("[OFFSET="))
47 | {
48 |
49 | if (!(textBoxUrl.Text.Contains("[PRESET]") && textBoxUrl.Text.Contains("[OFFSET=")))
50 | {
51 |
52 | DialogResult = DialogResult.OK;
53 | _camera.Contact.PresetSettings.PresetMethod = PTZMethod.HTTP;
54 | _camera.Contact.PresetSettings.PresetList.Clear();
55 | _camera.Contact.PresetSettings.CameraMake = _camera.CameraPrefix.ToLower();
56 |
57 | string str = textBoxUrl.Text;
58 | if (!textBoxUrl.Text.Contains("[ADDRESS]"))
59 | {
60 | str = "http://[ADDRESS]" + textBoxUrl.Text;
61 | }
62 |
63 | // Yes, each preset has the same contents -- there can be only one!
64 | for (int i = 0; i < 256; i++)
65 | {
66 | Preset preset = new ();
67 | preset.Name = "Preset " + i.ToString();
68 | preset.Command = str;
69 | _camera.Contact.PresetSettings.PresetList.Add(preset);
70 | }
71 | }
72 | else
73 | {
74 | MessageBox.Show(this, "Your URL CANNOT contain BOTH [PRESET] OR [OFFSET=", "Invalid URL format");
75 | }
76 | }
77 | else
78 | {
79 | MessageBox.Show(this, "Your URL must contain either [PRESET] OR [OFFSET=", "Invalid URL format");
80 | }
81 | }
82 |
83 | }
84 |
85 | private void CancelButton_Click(object sender, EventArgs e)
86 | {
87 | DialogResult = DialogResult.Cancel;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/Forms/HTTPptz.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class HTTPptz : Form
14 | {
15 | CameraData _camera;
16 | public HTTPptz(CameraData camera)
17 | {
18 | _camera = camera;
19 | InitializeComponent();
20 |
21 | textBoxLeft.Text = _camera.Contact.HTTPPanLeft;
22 | textBoxRight.Text = _camera.Contact.HTTPPanRight;
23 | textBoxUp.Text = _camera.Contact.HTTPPanUp;
24 | textBoxDown.Text = _camera.Contact.HTTPPanDown;
25 | textBoxZoomIn.Text = _camera.Contact.HTTPZoomIn;
26 | textBoxZoomOut.Text = _camera.Contact.HTTPZoomOut;
27 | textBoxStop.Text = _camera.Contact.HTTPStop;
28 | }
29 |
30 | private void OKButton_Click(object sender, EventArgs e)
31 | {
32 | if (!string.IsNullOrEmpty(textBoxLeft.Text) && !string.IsNullOrEmpty(textBoxRight.Text))
33 | {
34 | _camera.Contact.HTTPPanLeft = textBoxLeft.Text;
35 | _camera.Contact.HTTPPanRight = textBoxRight.Text;
36 | _camera.Contact.HTTPPanUp = textBoxUp.Text;
37 | _camera.Contact.HTTPPanDown = textBoxDown.Text;
38 | _camera.Contact.HTTPZoomIn = textBoxZoomIn.Text;
39 | _camera.Contact.HTTPZoomOut = textBoxZoomOut.Text;
40 | _camera.Contact.HTTPStop = textBoxStop.Text;
41 | _camera.Contact.PTZContactMethod = PTZMethod.HTTP;
42 | DialogResult = DialogResult.OK;
43 | }
44 | else
45 | {
46 | MessageBox.Show(this, "At a minimum you must provide a definition for Left and Right", "Missing Values!");
47 | }
48 | }
49 |
50 | private void CancelButton_Click(object sender, EventArgs e)
51 | {
52 |
53 | if (!string.IsNullOrEmpty(textBoxLeft.Text) && !string.IsNullOrEmpty(textBoxRight.Text))
54 | {
55 | if (MessageBox.Show(this, "You have made entries. Are you sure you wish to exit?", "Exit?", MessageBoxButtons.YesNo) == DialogResult.Yes)
56 | {
57 | DialogResult = DialogResult.Cancel;
58 | }
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Forms/HTTPptz.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/HelpBox.cs:
--------------------------------------------------------------------------------
1 | using Microsoft;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Data;
6 | using System.Drawing;
7 | using OnGuardCore.Src.Properties;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | using System.Windows.Forms;
13 | using System.Resources;
14 | using System.IO;
15 | using System.Reflection;
16 |
17 | namespace OnGuardCore
18 | {
19 | public partial class HelpBox : Form
20 | {
21 | public HelpBox(string title, Size size, string helpFileName)
22 | {
23 | InitializeComponent();
24 |
25 | this.Size = size;
26 |
27 | // Microsoft Sans Serif; bold 10
28 | Font font = new ("Microsoft Sans Serif", 10.0F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
29 | Size strSize = TextRenderer.MeasureText(title, font);
30 | TitleLabel.Location = new Point(this.Width/2 - (strSize.Width)/2, 20);
31 | TitleLabel.Text = title;
32 | OKButton.Location = new Point(size.Width / 2 - OKButton.Width / 2, ClientRectangle.Height - OKButton.Height - 5);
33 |
34 | richTextBoxHelp.SelectAll();
35 |
36 | this.richTextBoxHelp.SelectAll();
37 |
38 | string resName = "OnGuardCore.Resources.HelpFiles." + helpFileName;
39 | var assembly = Assembly.GetExecutingAssembly();
40 |
41 | using Stream stream = assembly.GetManifestResourceStream(resName);
42 | using StreamReader reader = new (stream);
43 | richTextBoxHelp.SelectedRtf = reader.ReadToEnd();
44 |
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Forms/HelpBox.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/HttpSnapshot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class HttpSnapshot : Form
14 | {
15 | CameraData _camera;
16 |
17 | public HttpSnapshot(CameraData camera)
18 | {
19 | _camera = camera;
20 | InitializeComponent();
21 | }
22 |
23 | private void OKButton_Click(object sender, EventArgs e)
24 | {
25 | _camera.Contact.JPGSnapshotURL = textBoxURL.Text;
26 | _camera.Contact.JpgContactMethod = PTZMethod.HTTP;
27 | DialogResult = DialogResult.OK;
28 | }
29 |
30 | private void CancelButton_Click(object sender, EventArgs e)
31 | {
32 | DialogResult = DialogResult.Cancel;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Forms/ISpyPTZ.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
61 | Changes made to the URL text box will be applied to the URL in the Directions list above when you select a different direction or press OK. However, they will not (ever) be applied to the model list.
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/Forms/ISpySnapshot.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/ImageCaptureDialog.cs:
--------------------------------------------------------------------------------
1 | using OnGuardCore;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Data;
6 | using System.Drawing;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 |
12 | namespace OnGuardCore
13 | {
14 | public partial class ImageCaptureDialog : Form
15 | {
16 | CameraData _camera;
17 | public ImageCaptureDialog(CameraData camera)
18 | {
19 | _camera = camera;
20 | InitializeComponent();
21 |
22 | int maxEvent = Storage.Instance.GetGlobalInt("MaxEventTime");
23 | if (maxEvent != 0)
24 | {
25 | maxEventNumeric.Value = maxEvent;
26 | }
27 |
28 | int eventInterval = Storage.Instance.GetGlobalInt("EventInterval");
29 | if (eventInterval != 0)
30 | {
31 | eventIntervalNumeric.Value = eventInterval;
32 | }
33 |
34 | double snapshot = Storage.Instance.GetGlobalDouble("FrameInterval");
35 | if (snapshot != 0.0)
36 | {
37 | snapshotNumeric.Value = (decimal)snapshot;
38 | }
39 |
40 | }
41 | private void OKButton_Click(object sender, EventArgs e)
42 | {
43 | Storage.Instance.SetGlobalDouble("FrameInterval", (double)snapshotNumeric.Value);
44 | Storage.Instance.SetGlobalInt("MaxEventTime", (int)maxEventNumeric.Value);
45 | Storage.Instance.SetGlobalInt("EventInterval", (int)eventIntervalNumeric.Value);
46 | Storage.Instance.Update();
47 | DialogResult = DialogResult.OK;
48 | }
49 |
50 | private void CancelButton_Click(object sender, EventArgs e)
51 | {
52 | DialogResult = DialogResult.Cancel;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Forms/InitialPictureBehaviorDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class InitialPictureBehaviorDialog : Form
14 | {
15 | public PictureDateBehavior Behavior { get; set; }
16 |
17 | public InitialPictureBehaviorDialog(PictureDateBehavior behavior, DateTime searchDate)
18 | {
19 | Behavior = behavior;
20 | InitializeComponent();
21 |
22 | switch (Behavior)
23 | {
24 | case PictureDateBehavior.Picture1:
25 | radioButtonPicture1.Checked = true;
26 | break;
27 |
28 | case PictureDateBehavior.SearchDate:
29 | radioButtonEnteredDateTime.Checked = true;
30 | break;
31 |
32 | case PictureDateBehavior.LastViewed:
33 | radioButtonLastViewed.Checked = true;
34 | break;
35 | }
36 |
37 | if (searchDate == DateTime.MinValue)
38 | {
39 | radioButtonEnteredDateTime.Enabled = false; // You can't select this if there isn't one.
40 | }
41 | }
42 |
43 |
44 | private void ButtonCancel_Click(object sender, EventArgs e)
45 | {
46 | DialogResult = DialogResult.Cancel;
47 | this.Close();
48 | }
49 |
50 | private void buttonOK_Click(object sender, EventArgs e)
51 | {
52 | DialogResult = DialogResult.OK;
53 |
54 | if (radioButtonPicture1.Checked)
55 | {
56 | Behavior = PictureDateBehavior.Picture1;
57 | }
58 | else if (radioButtonEnteredDateTime.Checked)
59 | {
60 | Behavior = PictureDateBehavior.SearchDate;
61 | }
62 | else
63 | {
64 | Behavior = PictureDateBehavior.LastViewed;
65 | }
66 |
67 | this.Close();
68 | }
69 | }
70 |
71 | public enum PictureDateBehavior
72 | {
73 | Picture1,
74 | SearchDate,
75 | LastViewed
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Forms/InterestingItemsDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows.Forms;
4 |
5 | namespace OnGuardCore
6 | {
7 | public partial class InterestingItemsDialog : Form
8 | {
9 | public InterestingItemsDialog(AnalysisResult analysisResult)
10 | {
11 | InitializeComponent();
12 |
13 | foreach (var interest in analysisResult.InterestingObjects)
14 | {
15 | ListViewItem item = new()
16 | {
17 | Text = interest.Area.AOIName
18 | };
19 |
20 | double screenWidthPercent = Math.Round((100.0 * interest.ObjectRectangle.Width) / BitmapResolution.XResolution, 1, MidpointRounding.AwayFromZero);
21 | double screenHeightPercent = Math.Round((100.0 * interest.ObjectRectangle.Height) / BitmapResolution.YResolution, 1, MidpointRounding.AwayFromZero);
22 |
23 | item.SubItems.Add(interest.Area.AOIType.ToString());
24 | item.SubItems.Add(interest.Label);
25 | item.SubItems.Add(interest.Confidence.ToString());
26 | item.SubItems.Add(interest.Overlap.ToString());
27 | item.SubItems.Add(screenWidthPercent.ToString());
28 | item.SubItems.Add(screenHeightPercent.ToString());
29 |
30 | interestingListView.Items.Add(item);
31 |
32 | }
33 |
34 | foreach (string item in analysisResult.FailureReasons)
35 | {
36 | failuresList.Items.Add(item);
37 | }
38 |
39 |
40 | }
41 |
42 | private void DoneButton_Click(object sender, EventArgs e)
43 | {
44 | DialogResult = DialogResult.OK;
45 | }
46 |
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Forms/InterestingItemsDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/MMS-Helper.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
61 | Note: If you try to send too many pictures or you don't resize your picture small enough your carrier may refuse to accept the message, or it may scale pictures down. Your carrier may or may not return any error messages to On Guard.
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/Forms/ModelessMessageWindow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class ModelessMessageWindow : Form
14 | {
15 | Timer _timer;
16 | public ModelessMessageWindow(Control parent, string title, string message, bool button)
17 | {
18 |
19 | _timer = new Timer();
20 | _timer.Interval = 100;
21 | _timer.Tick += _timer_Tick;
22 |
23 |
24 | InitializeComponent();
25 | SetLabel(title, message);
26 | if (button)
27 | {
28 | DismissButton.Visible = true;
29 | DismissButton.Enabled = true;
30 | }
31 |
32 | _timer.Start();
33 | }
34 |
35 | private void _timer_Tick(object sender, EventArgs e)
36 | {
37 | if (this.WindowState == FormWindowState.Normal)
38 | {
39 | this.BringToFront();
40 | this.Update();
41 | }
42 | }
43 |
44 |
45 | private void Button_Click(object sender, EventArgs e)
46 | {
47 | _timer?.Stop();
48 | this.Hide();
49 | }
50 |
51 | public void SetLabel(string title, string message)
52 | {
53 | LabelMessage.Text = message;
54 | this.Text = title;
55 | var size = TextRenderer.MeasureText(message, LabelMessage.Font);
56 | if (size.Width > this.ClientRectangle.Width - 10)
57 | {
58 | this.Width = size.Width + 12;
59 | DismissButton.Left = (Width / 2) - DismissButton.Width / 2;
60 | }
61 |
62 | LabelMessage.Left = this.Width / 2 - size.Width / 2;
63 | this.Show();
64 | this.BringToFront();
65 | this.Update();
66 | }
67 |
68 | public void Destroy()
69 | {
70 | DialogResult = DialogResult.None;
71 | this.Close();
72 | }
73 |
74 | private void OnClosed(object sender, FormClosedEventArgs e)
75 | {
76 | DialogResult = DialogResult.None;
77 | }
78 |
79 | private void OnClosing(object sender, FormClosingEventArgs e)
80 | {
81 | DialogResult = DialogResult.None;
82 | }
83 |
84 | private void OnVisibleChanged(object sender, EventArgs e)
85 | {
86 | if (this.Visible)
87 | {
88 | this.BringToFront();
89 | _timer?.Start();
90 | }
91 | else
92 | {
93 | _timer?.Stop();
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/Forms/ModelessMessageWindow.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/ObjectDefinitionDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class ObjectDefinitionDialog : Form
14 | {
15 | public string ObjectType { get; set; }
16 | public int Confidence { get; set; }
17 | public int Overlap { get; set; }
18 | public int MinX { get; set; }
19 | public int MinY { get; set; }
20 |
21 | public ObjectDefinitionDialog()
22 | {
23 | InitializeComponent();
24 | }
25 |
26 | public ObjectDefinitionDialog(ObjectCharacteristics src)
27 | {
28 | InitializeComponent();
29 |
30 | if (null != src)
31 | {
32 | int index = ObjectCombo.FindString(src.ObjectType);
33 | ObjectCombo.SelectedIndex = index;
34 | ConfidenceNumeric.Value = src.Confidence;
35 | overlapNumeric.Value = src.MinPercentOverlap;
36 | minWidthNumeric.Value = src.MinimumXSize;
37 | minHeightNumeric.Value = src.MinimumYSize;
38 | }
39 |
40 | }
41 |
42 | private void OKButton_Click(object sender, EventArgs e)
43 | {
44 | if (ObjectCombo.SelectedIndex >= 0)
45 | {
46 | ObjectType = ObjectCombo.SelectedItem.ToString();
47 | Confidence = (int)ConfidenceNumeric.Value;
48 | Overlap = (int)overlapNumeric.Value;
49 | MinX = (int)minWidthNumeric.Value;
50 | MinY = (int)minHeightNumeric.Value;
51 | DialogResult = DialogResult.OK;
52 | }
53 | else
54 | {
55 | MessageBox.Show(this, "You must select an item from the Object Type list!", "Select an Object!");
56 | DialogResult = DialogResult.None;
57 | }
58 | }
59 |
60 | private void CancelButton_Click(object sender, EventArgs e)
61 | {
62 | DialogResult = DialogResult.Cancel;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Forms/ObjectDefinitionDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/OnGuardDataDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/OnVIFSnapshot.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/OutgoingEmailDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/PictureDateSelect.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class PictureDateSelect : Form
14 | {
15 | public DateTime SearchDateTime { get; set; }
16 | public bool KeepDateTime { get; set; }
17 | DateTime _currentPicture;
18 | TimeOnly _timeOnly;
19 |
20 | public PictureDateSelect(DateTime dateTime, DateTime currentPicture)
21 | {
22 | InitializeComponent();
23 |
24 | _currentPicture = currentPicture;
25 | if (dateTime != DateTime.MinValue)
26 | {
27 | SearchDateTime = dateTime;
28 | }
29 | else
30 | {
31 | SearchDateTime = DateTime.Now;
32 | }
33 |
34 | PictureDate.Value = SearchDateTime.Date;
35 | PictureTime.Value = SearchDateTime;
36 |
37 | }
38 |
39 | private void CancelButton_Click(object sender, EventArgs e)
40 | {
41 | DialogResult = DialogResult.Cancel;
42 | this.Close();
43 | }
44 |
45 | private void OKButton_Click(object sender, EventArgs e)
46 | {
47 | SearchDateTime = new DateTime(PictureDate.Value.Year, PictureDate.Value.Month, PictureDate.Value.Day, PictureTime.Value.Hour, PictureTime.Value.Minute, PictureTime.Value.Second); ;
48 | KeepDateTime = KeepDateCheckbox.Checked;
49 | DialogResult = DialogResult.OK;
50 | this.Close();
51 | }
52 |
53 | private void CurrentPictureButton_Click(object sender, EventArgs e)
54 | {
55 | PictureDate.Value = _currentPicture.Date;
56 | PictureTime.Value = _currentPicture.ToLocalTime();
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Forms/PictureDateSelect.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/ScheduledPreset.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/SetLogLevelDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class SetLogLevelDialog : Form
14 | {
15 | public SetLogLevelDialog()
16 | {
17 | InitializeComponent();
18 |
19 | switch (Dbg.Level)
20 | {
21 | case (int)LogLevel.Verbose:
22 | radioVerbose.Checked = true;
23 | break;
24 |
25 | case (int)LogLevel.DetailedInfo:
26 | radioDetailedInfo.Checked = true;
27 | break;
28 |
29 | case (int)LogLevel.Info:
30 | radioInfo.Checked = true;
31 | break;
32 |
33 | case (int)LogLevel.Warning:
34 | radioWarning.Checked = true;
35 | break;
36 |
37 | case (int)(LogLevel.Error):
38 | radioError.Checked = true;
39 | break;
40 |
41 | }
42 | }
43 |
44 | private void OK_Click(object sender, EventArgs e)
45 | {
46 | if (radioVerbose.Checked)
47 | {
48 | Dbg.SetLogLevel(LogLevel.Verbose);
49 | }
50 | else if (radioDetailedInfo.Checked)
51 | {
52 | Dbg.SetLogLevel(LogLevel.DetailedInfo);
53 | }
54 | else if (radioInfo.Checked)
55 | {
56 | Dbg.SetLogLevel(LogLevel.Info);
57 | }
58 | else if (radioWarning.Checked)
59 | {
60 | Dbg.SetLogLevel(LogLevel.Warning);
61 | }
62 | else if (radioError.Checked)
63 | {
64 | Dbg.SetLogLevel(LogLevel.Error);
65 | }
66 |
67 | Storage.Instance.SetGlobalInt("LogLevel", (int)Dbg.Level); // yes, we just set it
68 | Storage.Instance.Update();
69 | this.Close();
70 | }
71 |
72 | private void CancelButton_Click(object sender, EventArgs e)
73 | {
74 | this.Close();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Forms/SettingsDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/StartRestartAI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class StartRestartAI : Form
14 | {
15 | public bool AIRunning { get; set; }
16 | public StartRestartAI()
17 | {
18 | InitializeComponent();
19 |
20 | if (!AI.IsAIRunning())
21 | {
22 | StatusLabel.Text = "NOT Running";
23 | StopButton.Enabled = false;
24 | StartButton.Text = "Start";
25 | }
26 | else
27 | {
28 | AIRunning = true;
29 | StartButton.Text = "Restart";
30 | StopButton.Enabled = true;
31 | }
32 | }
33 |
34 | private void DoneButton_Click(object sender, EventArgs e)
35 | {
36 | DialogResult = DialogResult.OK;
37 | }
38 |
39 | private void StartButton_Click(object sender, EventArgs e)
40 | {
41 | if (MessageBox.Show(this, "Starting/Restarting/Stopping the DeepStack AI may result in application instability. Proceeed?", "Warning!", MessageBoxButtons.YesNo) == DialogResult.Yes)
42 | {
43 | AIRunning = AI.RestartAI(true, true);
44 |
45 | if (AIRunning)
46 | {
47 | StatusLabel.Text = "Running";
48 | StopButton.Enabled = true;
49 | }
50 | else
51 | {
52 | StatusLabel.Text = "NOT Running - Start/Restart Failed";
53 | StopButton.Enabled = false;
54 | StartButton.Text = "Start";
55 | }
56 | }
57 | }
58 |
59 | private void StopButton_Click(object sender, EventArgs e)
60 | {
61 | if (MessageBox.Show(this, "Starting/Restarting/Stopping the DeepStack AI may result in application instability. Proceeed?", "Warning!", MessageBoxButtons.YesNo) == DialogResult.Yes)
62 | {
63 | AIRunning = false;
64 | AI.StopAI();
65 | StatusLabel.Text = "NOT Running";
66 | StopButton.Enabled = false;
67 | StartButton.Text = "Start";
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Forms/StartRestartAI.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/SyncToDatabaseDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class SyncToDatabaseDialog : Form
14 | {
15 | private double _interval;
16 | public double Interval { get => _interval; }
17 |
18 | public SyncToDatabaseDialog()
19 | {
20 | InitializeComponent();
21 | }
22 |
23 | private void OkButton_Click(object sender, EventArgs e)
24 | {
25 | _interval = (double)IntervalNumeric.Value;
26 | DialogResult = DialogResult.OK;
27 | }
28 |
29 | private void CancelButton_Click(object sender, EventArgs e)
30 | {
31 | DialogResult = DialogResult.Cancel;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Forms/Test Email Address.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace OnGuardCore
12 | {
13 | public partial class TestEmailAddress : Form
14 | {
15 | public TestEmailAddress()
16 | {
17 | InitializeComponent();
18 | }
19 |
20 | private void OKButton_Click(object sender, EventArgs e)
21 | {
22 | DialogResult = DialogResult.OK;
23 | Close();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Forms/Test Email Address.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/TestPIcturesDialog.cs:
--------------------------------------------------------------------------------
1 | using OnGuardCore.Src.Properties;
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Data;
7 | using System.Drawing;
8 | using System.Drawing.Imaging;
9 | using System.Globalization;
10 | using System.IO;
11 | using System.Linq;
12 | using System.Resources;
13 | using System.Text;
14 | using System.Threading.Tasks;
15 | using System.Windows.Forms;
16 |
17 | namespace OnGuardCore
18 | {
19 | public partial class TestPIcturesDialog : Form
20 | {
21 | CameraCollection _cameras;
22 | public TestPIcturesDialog(CameraCollection cameras)
23 | {
24 | _cameras = cameras;
25 | InitializeComponent();
26 | CameraData cam;
27 |
28 | ((ListBox)this.checkedListBoxCameras).DataSource = _cameras.CameraDictionary.Values.ToArray();
29 | ((ListBox)this.checkedListBoxCameras).DisplayMember = "CameraPrefix";
30 |
31 | for (int i = 0; i < checkedListBoxCameras.Items.Count; i++)
32 | {
33 | checkedListBoxCameras.SetItemChecked(i, true);
34 | }
35 | }
36 |
37 | private void ButtonOK_Click(object sender, EventArgs e)
38 | {
39 |
40 | ResourceSet allPics = SamplePictureResources.ResourceManager.GetResourceSet(CultureInfo.InvariantCulture, true, true);
41 |
42 | foreach (int itemChecked in checkedListBoxCameras.CheckedIndices)
43 | {
44 | CameraData camera = (CameraData)(checkedListBoxCameras.Items[itemChecked]);
45 |
46 | IDictionaryEnumerator dict = allPics.GetEnumerator();
47 |
48 | while (dict.MoveNext())
49 | {
50 | Bitmap bm = (Bitmap)dict.Value;
51 | using MemoryStream mem = new();
52 | string fullPath = CameraData.PathAndPrefix(camera);
53 | fullPath += DateTime.Now.Ticks.ToString() + ".jpg";
54 | bm.Save(fullPath, ImageFormat.Jpeg);
55 | }
56 | }
57 |
58 | DialogResult = DialogResult.OK;
59 | this.Close();
60 | }
61 |
62 | private void ButtonCancel_Click(object sender, EventArgs e)
63 | {
64 |
65 | DialogResult = DialogResult.Cancel;
66 | this.Close();
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/Forms/TestPIcturesDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/TestPresets.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/src/Forms/iSpyPreset.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
61 | 17, 17
62 |
63 |
--------------------------------------------------------------------------------
/src/FrameAccumulator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace OnGuardCore
8 | {
9 |
10 | public abstract class FrameAccumulator : IDisposable
11 | {
12 |
13 | public delegate void EmailAccumulated(SortedList frames);
14 |
15 | SortedList Frames { get; set; }
16 |
17 | protected readonly object _lock = new ();
18 | public int TimeToAccumulate { get; set; }
19 | protected bool DisposedValue { get => disposedValue; set => disposedValue = value; }
20 |
21 | protected System.Threading.Timer _timer;
22 | private bool disposedValue = false; // To detect redundant calls
23 |
24 |
25 | public void Init(int timeToAccumulate)
26 | {
27 | TimeToAccumulate = timeToAccumulate;
28 | Frames = new SortedList();
29 | }
30 |
31 | public void Add(Frame frame)
32 | {
33 | lock (_lock)
34 | {
35 | Frames.Add(frame.Item.TimeEnqueued, frame);
36 | if (null == _timer)
37 | {
38 | _timer = new System.Threading.Timer(DoneAccumulating, null, TimeToAccumulate * 1000, 0);
39 | }
40 | }
41 |
42 | }
43 |
44 | // This triggers when the timer expires or when we have the number of frames we were expecting
45 | void DoneAccumulating(object obj)
46 | {
47 | lock (_lock)
48 | {
49 | _timer = null;
50 |
51 | if (Frames.Values.Count > 0)
52 | {
53 | lock (Frames.Values[0].Item.CamData.AccumulateLock)
54 | {
55 | Frames.Values[0].Item.CamData.Accumulating = false; // no longer accumulating
56 | Frames.Values[0].Item.CamData.TimeLastAccumulatorCompleted = DateTime.Now;
57 | }
58 | }
59 |
60 | List aCopy = new ();
61 |
62 | foreach (Frame frame in Frames.Values)
63 | {
64 | Frame cpy = new (frame);
65 | aCopy.Add(cpy);
66 | }
67 |
68 | ProcessAccumulatedFrames(aCopy);
69 | Frames.Clear();
70 | }
71 | }
72 |
73 |
74 |
75 | protected virtual void Dispose(bool disposing)
76 | {
77 | if (!DisposedValue)
78 | {
79 | if (disposing)
80 | {
81 | lock (_lock)
82 | {
83 | if (_timer != null) _timer.Dispose();
84 | }
85 | }
86 |
87 | DisposedValue = true;
88 | }
89 | }
90 |
91 |
92 | public void Dispose()
93 | {
94 | Dispose(true);
95 | GC.SuppressFinalize(this);
96 | }
97 |
98 | public abstract void ProcessAccumulatedFrames(List frames);
99 |
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/GlobalData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 |
8 | namespace OnGuardCore
9 | {
10 | public static class GlobalData
11 | {
12 | public static int AreaGridX { get => 64; } // may be settable in the future
13 | public static int AreaGridY { get => 64; }
14 |
15 | }
16 |
17 | public static class GlobalFunctions
18 | {
19 | public static string GetUniqueFileName(string fileName)
20 | {
21 | string result = string.Empty;
22 | if (!string.IsNullOrEmpty(fileName))
23 | {
24 | FileInfo fi = new FileInfo(fileName);
25 | if (fi.Exists)
26 | {
27 | long fileTime = fi.CreationTime.ToFileTime();
28 | result = GetFileKey(fi, fileName);
29 | }
30 | }
31 |
32 | return result;
33 | }
34 |
35 | public static string GetFileKey(FileInfo fi, string fileName)
36 | {
37 | string result = string.Empty;
38 | if (!string.IsNullOrEmpty(fileName))
39 | {
40 | long fileTime = fi.CreationTime.ToFileTime();
41 | result = $"{fileTime,0:0000000000000000000}-{Path.GetFileName(fileName).ToLower()}";
42 | result = result.ToLower();
43 | }
44 |
45 | return result;
46 | }
47 |
48 | public static string GetComparisonKey(DateTime compTime)
49 | {
50 | string result = string.Empty;
51 | long fileTime = compTime.ToFileTime();
52 | result = $"{fileTime,0:0000000000000000000}-";
53 | return result;
54 | }
55 |
56 |
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Usage", "CA2200:Rethrow to preserve stack details.", Justification = "", Scope = "member", Target = "~M:OnGuardCore.AIAnalyzer.AIProcessFromUI(System.IO.Stream,System.String)~System.Threading.Tasks.Task{System.Collections.Generic.List{OnGuardCore.InterestingObject}}")]
9 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "member", Target = "~P:OnGuardCore.InterestingObject.Y_min")]
10 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "member", Target = "~P:OnGuardCore.InterestingObject.X_min")]
11 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "member", Target = "~P:OnGuardCore.InterestingObject.Y_max")]
12 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "member", Target = "~P:OnGuardCore.InterestingObject.X_max")]
13 | [assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "member", Target = "~F:OnGuardCore.AreaOfInterest.AreaRect")]
14 | [assembly: SuppressMessage("Usage", "CA2200:Rethrow to preserve stack details.", Justification = "", Scope = "member", Target = "~M:OnGuardCore.MainWindow.LoadImage(System.String)~System.Collections.Generic.List{OnGuardCore.InterestingObject}")]
15 | [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:OnGuardCore.MainWindow.PresetButton_Click(System.Object,System.EventArgs)")]
16 | [assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "", Scope = "member", Target = "~M:OnGuardCore.MQTTPublish.CreateClient~System.Threading.Tasks.Task")]
17 | [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:OnGuardCore.MQTTPublish.Connect~System.Threading.Tasks.Task")]
18 | [assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "member", Target = "~F:OnGuardCore.EmailOptions.DaysOfWeek")]
19 | [assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "member", Target = "~F:OnGuardCore.CameraData.AOI")]
20 | [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:OnGuardCore.EmailAccumulator.SendEmailAsync(System.String,System.String[],System.String[])~System.Threading.Tasks.Task")]
21 | [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:OnGuardCore.MainWindow.InsertMotionIfNecessary(System.String)")]
22 |
--------------------------------------------------------------------------------
/src/IStorage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Microsoft.Win32;
4 |
5 | namespace OnGuardCore
6 | {
7 | public interface IStorage
8 | {
9 | void CreateBaseTree();
10 | void DeleteArea(string cameraPath, string cameraPrefix, AreaOfInterest area);
11 | AILocation GetAILocation();
12 | SortedDictionary GetAllAreas(string cameraPath, string cameraPrefix);
13 | CameraCollection GetAllCameras();
14 | string GetAppVersion();
15 | int GetCameraInt(string cameraPath, string cameraPrefix, string keyName);
16 | List GetEmailAddresses();
17 | object GetValue(string keyName);
18 | bool GetGlobalBool(string keyName);
19 | bool GetGlobalBool(string keyName, bool useDefault);
20 | double GetGlobalDouble(string keyName);
21 | int GetGlobalInt(string keyName);
22 | int GetGlobalIntWithDefault(string keyName, int defaultValue);
23 | int GetGlobalIntExcept(string keyName);
24 | string GetGlobalString(string keyName);
25 | string GetGlobalStringNull(string keyName);
26 | void RemoveGlobalValue(string valueName);
27 | void SaveAllAreas(string cameraPath, string cameraPrefix, AreasOfInterestCollection areas);
28 | void SaveArea(AreaOfInterest area);
29 | void SaveArea(CameraData cam, AreaOfInterest area);
30 | void SaveArea(string cameraPath, string cameraPrefix, AreaOfInterest area);
31 | void SaveCameras(CameraCollection allCameras);
32 | void SaveEmailAddresses(List addresses);
33 | void SetAILocation(string ipAddress, int port);
34 | void SetAppVersion(string version);
35 | void SetCameraInt(string cameraPath, string cameraPrefix, string keyName, int theValue);
36 | void SetGlobalBool(string keyName, bool value);
37 | void SetGlobalDouble(string keyName, double value);
38 | void SetGlobalInt(string keyName, int value);
39 | void SetGlobalString(string keyName, string value);
40 | void Update();
41 | }
42 | }
--------------------------------------------------------------------------------
/src/ImageObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace OnGuardCore
9 | {
10 | public class InterestingObject
11 | {
12 | public InterestingObject()
13 | {
14 | ID = Guid.NewGuid();
15 | Label = "none";
16 |
17 | // Some unnecessary initializations, but...
18 | Success = false;
19 | InMotion = false;
20 | Confidence = 80.0;
21 | X_min = 0;
22 | Y_min = 0;
23 | X_max = 0;
24 | Y_max = 0;
25 | IsFace = false;
26 | }
27 |
28 | public bool Success { get; set; }
29 | public string Label { get; set; }
30 | public double Confidence { get; set; }
31 | public int Y_min { get; set; }
32 | public int X_min { get; set; }
33 | public int Y_max { get; set; }
34 | public int X_max { get; set; }
35 | public Rectangle ObjectRectangle { get; set; }
36 | public bool InMotion { get; set; }
37 | public Guid ID { get; set; }
38 | public bool IsFace { get; set; }
39 | public AreaOfInterest Area { get; set; }
40 | public int Overlap { get; set; }
41 | public bool IsOfCameraInterest { get; set; }
42 |
43 |
44 | public InterestingObject(InterestingObject src)
45 | {
46 | if (src != null)
47 | {
48 | Label = src.Label;
49 | Success = src.Success;
50 | Confidence = src.Confidence;
51 | Y_max = src.Y_max;
52 | Y_min = src.Y_min;
53 | X_max = src.X_max;
54 | X_min = src.Y_min;
55 | ObjectRectangle = src.ObjectRectangle;
56 | InMotion = src.InMotion;
57 | ID = src.ID;
58 | IsFace = src.IsFace;
59 |
60 | }
61 | }
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/MostRecentCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace OnGuardCore
5 | {
6 |
7 | ///
8 | /// A class to clollect a list of recent values.
9 | /// In this case it is used to track AI processing time
10 | /// so we can average them out.
11 | ///
12 | public class MostRecentCollection : List
13 | {
14 | public int MaxItems { get; }
15 | readonly object _lock = new object();
16 |
17 | public MostRecentCollection(int numberOfItems)
18 | {
19 | MaxItems = numberOfItems;
20 | }
21 |
22 | public void AddValue(double v)
23 | {
24 | lock (_lock)
25 | {
26 | if (Count == MaxItems)
27 | {
28 | RemoveAt(0);
29 | }
30 |
31 | Add(v);
32 | }
33 | }
34 |
35 | public double Avg()
36 | {
37 | double result;
38 |
39 | lock (_lock)
40 | {
41 | result = 0.0;
42 |
43 | if (Count > 0)
44 | {
45 | result = this.Average();
46 | }
47 |
48 | }
49 | return result;
50 | }
51 |
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/MotionDatabase.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Data.Sqlite;
2 | using Microsoft.EntityFrameworkCore;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace OnGuardCore
10 | {
11 | public class MotionDBContext : DbContext
12 | {
13 | static string s_connectionString;
14 | static bool s_setWalMode = false;
15 |
16 | public static void SetupDatabase(string dbPath)
17 | {
18 | s_connectionString = $@"Data Source={dbPath}\MotionInfo.db";
19 |
20 | bool exists = DoesMotionDatabaseExist($@"{dbPath}\MotionInfo.db");
21 | if (!exists)
22 | {
23 | CreateMotionDatabase();
24 | }
25 | }
26 |
27 | public MotionDBContext()
28 | {
29 | if (!s_setWalMode)
30 | {
31 | using var connection = this.Database.GetDbConnection();
32 | connection.Open();
33 | using (var command = connection.CreateCommand())
34 | {
35 | command.CommandText = "PRAGMA journal_mode=WAL;";
36 | command.ExecuteNonQuery();
37 | }
38 | }
39 | }
40 |
41 |
42 | protected override void OnConfiguring(DbContextOptionsBuilder dbContextOptionsBuilder)
43 | {
44 | dbContextOptionsBuilder.UseSqlite(s_connectionString);
45 | }
46 |
47 | public DbSet MotionInfo { get; set; }
48 |
49 | public static void CreateMotionDatabase()
50 | {
51 | try
52 | {
53 | using SqliteConnection con = new(s_connectionString);
54 | con.Open();
55 | using SqliteCommand cmd = con.CreateCommand();
56 |
57 | cmd.CommandText = "CREATE TABLE MotionInfo " +
58 | "(UniqueName VARCHAR(100) PRIMARY KEY DESC, " +
59 | "FileName VARCHAR(256), " +
60 | "Path VARCHAR(2056), " +
61 | "Camera VARCHAR(100), " +
62 | "PictureTime DATETIME);";
63 |
64 | cmd.ExecuteNonQuery();
65 |
66 | cmd.CommandText = "CREATE UNIQUE INDEX idxReverseUniqueName on MotionInfo (UniqueName ASC);";
67 | cmd.ExecuteNonQuery();
68 | }
69 | catch (Exception ex)
70 | {
71 | Dbg.Write(LogLevel.Error, "Exception - MotionDatabase - CreateMotionDatabase: " + ex.Message);
72 | }
73 | }
74 |
75 | public static bool DoesMotionDatabaseExist(string dbPath)
76 | {
77 | bool result = false;
78 |
79 | if (System.IO.File.Exists(dbPath))
80 | {
81 | result = true;
82 |
83 | using SqliteConnection con = new(s_connectionString);
84 | con.Open();
85 |
86 | try
87 | {
88 | string query = "SELECT name FROM sqlite_master WHERE type='table' AND name='MotionInfo';";
89 | using SqliteCommand cmd = con.CreateCommand();
90 | cmd.CommandText = query;
91 | var queryResult = cmd.ExecuteScalar();
92 | if (null != queryResult)
93 | {
94 | result = true;
95 | }
96 | }
97 | catch (Exception ex)
98 | {
99 | result = false;
100 | }
101 | }
102 | return result;
103 | }
104 | }
105 | }
106 |
107 |
108 |
--------------------------------------------------------------------------------
/src/ObjectCharacteristics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace OnGuardCore
8 | {
9 |
10 | ///
11 | /// When defining an Area of Interest each object type in an area has optional
12 | /// characteristics that define when an object on the screen is consdiered
13 | /// "Interesting"
14 | ///
15 | [Serializable]
16 | public class ObjectCharacteristics
17 | {
18 | private string objectType;
19 | public int Confidence { get; set; } // Confidence values are very good in defining "people".
20 | public int MinPercentOverlap { get; set; } // A measurement for how much of an object must overlap the Area of Interest to be considered Interesting
21 | public int TimeFrame { get; set; } // Currently not implemented. When we determine movement direction this will define how many frames we look in
22 | public int MinimumXSize { get; set; } //In part this regulates how close the object is to the camera. I don't see a reason for maximum size
23 | public int MinimumYSize { get; set; } //In part this regulates how close the object is to the camera. I don't see a reason for maximum size
24 |
25 | public List Faces {get; set;}
26 |
27 | public string ObjectType { get => objectType; set => objectType = value; }
28 |
29 | public Guid ID { get; set; }
30 |
31 | public ObjectCharacteristics()
32 | {
33 | ID = Guid.NewGuid();
34 | objectType = "person";
35 | Confidence = 90;
36 | MinPercentOverlap = 50;
37 | TimeFrame = 1;
38 | MinimumXSize = 0;
39 | MinimumYSize = 0;
40 | Faces = new List();
41 | }
42 |
43 | public ObjectCharacteristics(ObjectCharacteristics src)
44 | {
45 | ID = src.ID;
46 | objectType = src.objectType;
47 | Confidence = src.Confidence;
48 | MinPercentOverlap = src.MinPercentOverlap;
49 | TimeFrame = src.TimeFrame;
50 | MinimumXSize = src.MinimumXSize;
51 | MinimumYSize = src.MinimumYSize;
52 | Faces = src.Faces;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/PendingItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Drawing;
4 |
5 | namespace OnGuardCore
6 | {
7 | ///
8 | /// A class to store information for recently changed/motion files.
9 | /// It tracks that information through the whole process of sending the information
10 | /// to the AI
11 | ///
12 | public class PendingItem : IDisposable
13 | {
14 | private bool disposedValue;
15 |
16 | public string CameraPath { get; }
17 | public string PendingFile { get; set; } // The file we want the AI to look at
18 | public Bitmap PictureImage{ get; set; }
19 | public DateTime TimeEnqueued { get; set; } // The time we put it in the queue waiting for the AI
20 | public DateTime TimeDispatched { get; set; } // The time the queue dispatched it to the AI
21 | public DateTime TimeCompleted { get; set; } // The time the AI completed the project and returned the item list
22 | public CameraData CamData { get; set; }
23 |
24 |
25 | public PendingItem(CameraData camData, string fileName)
26 | {
27 | CamData = camData;
28 | PendingFile = fileName;
29 | TimeEnqueued = DateTime.Now; // we only create one when we are ready to put it in the queue
30 | TimeCompleted = TimeEnqueued;
31 | TimeDispatched = TimeEnqueued;
32 | }
33 |
34 | public TimeSpan TimeInQueue()
35 | {
36 | return DateTime.Now - TimeEnqueued;
37 | }
38 |
39 | // Only call this when we are are ready to dispatch the item to the AI
40 | // It also (lamely) returns the time so far
41 | public TimeSpan TimeToDispatch()
42 | {
43 | TimeDispatched = DateTime.Now;
44 | return TimeDispatched - TimeEnqueued;
45 | }
46 |
47 | public TimeSpan SetTimeProcessingByAI()
48 | {
49 | TimeCompleted = DateTime.Now;
50 | return TimeCompleted - TimeDispatched;
51 | }
52 |
53 | public TimeSpan TotalProcessingTime()
54 | {
55 | TimeSpan result = TimeCompleted - TimeEnqueued;
56 | return result;
57 | }
58 |
59 | public TimeSpan AIProcessingTime()
60 | {
61 | TimeSpan result = TimeCompleted - TimeDispatched;
62 | return result;
63 | }
64 |
65 | protected virtual void Dispose(bool disposing)
66 | {
67 | if (!disposedValue)
68 | {
69 | if (disposing)
70 | {
71 | // dispose managed state (managed objects)
72 | // for now we will manually dispose the PictureImage when done with the bitmap
73 | /*if (null != PictureImage)
74 | {
75 | PictureImage.Dispose();
76 | }*/
77 | }
78 |
79 | disposedValue = true;
80 | }
81 | }
82 |
83 | public void Dispose()
84 | {
85 | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
86 | Dispose(disposing: true);
87 | GC.SuppressFinalize(this);
88 | }
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/src/PictureComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace OnGuardCore
8 | {
9 | public class PictureComparer : IComparer
10 | {
11 | public PictureOrder Order { get; set; }
12 |
13 | public PictureComparer()
14 | {
15 | Order = PictureOrder.Decending;
16 | }
17 |
18 | public void Reverse()
19 | {
20 | if (Order == PictureOrder.Ascending)
21 | {
22 | Order = PictureOrder.Decending;
23 | }
24 | else
25 | {
26 | Order = PictureOrder.Ascending;
27 | }
28 | }
29 |
30 | public int Compare(string first, string second)
31 | {
32 | int result = string.Compare(first, second);
33 |
34 | if (Order == PictureOrder.Decending)
35 | {
36 | result = 0 - result;
37 | }
38 |
39 | return result;
40 | }
41 |
42 | }
43 |
44 | public enum PictureOrder
45 | {
46 | Ascending,
47 | Decending
48 | }
49 | }
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/PictureInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.IO;
6 | using System.Threading.Tasks;
7 |
8 | namespace OnGuardCore
9 | {
10 | public class PictureInfo
11 | {
12 | public string FileName { get; }
13 | public string PictureKey { get; }
14 | public DateTime FileTime { get; set; }
15 |
16 | public PictureInfo(string fileName)
17 | {
18 | FileName = fileName.ToLower();
19 | FileInfo fi = new FileInfo(fileName);
20 | PictureKey = GlobalFunctions.GetFileKey(fi, fileName);
21 | FileTime = fi.CreationTime;
22 | }
23 |
24 | public override string ToString()
25 | {
26 | return FileName;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/PictureMotionInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace OnGuardCore
9 | {
10 | public class PictureMotionInfo
11 | {
12 | public PictureMotionInfo(string uniqueName, string fileName, string path, string camera, DateTime pictureTime)
13 | {
14 | UniqueName = uniqueName;
15 | FileName = fileName;
16 | Path = path;
17 | Camera = camera;
18 | PictureTime = pictureTime;
19 | }
20 |
21 | [Key]
22 | [Required]
23 | public string UniqueName { get; set; }
24 |
25 | [Required]
26 | [MaxLength(256)]
27 | public string FileName { get; set; } // The name of the file without path
28 |
29 | [Required]
30 | [MaxLength(2056)]
31 | public string Path { get; set; } // The path without name
32 |
33 | [Required]
34 | [MaxLength(100)]
35 | public string Camera { get; set; }
36 |
37 | [Required]
38 | public DateTime PictureTime { get; set; }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 | using System.Drawing;
7 |
8 | namespace OnGuardCore
9 | {
10 | static class Program
11 | {
12 | ///
13 | /// The main entry point for the application.
14 | ///
15 | [STAThread]
16 | static void Main()
17 | {
18 | MainWindow main = null;
19 |
20 | Application.SetHighDpiMode(HighDpiMode.DpiUnawareGdiScaled);
21 | Application.EnableVisualStyles();
22 | Font defaultFont = new ("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
23 | Application.SetDefaultFont(defaultFont);
24 | Application.SetCompatibleTextRenderingDefault(false);
25 |
26 | #if !DEBUG
27 | try
28 | #endif
29 | {
30 | Application.Run(main = new MainWindow());
31 | }
32 | #if !DEBUG
33 | catch (ObjectDisposedException)
34 | {
35 | }
36 |
37 | catch (Exception ex)
38 | {
39 | MessageBox.Show("There was an unexpected error in On Guard. Please report the following information: " + ex.Message, "Unexpected Error!");
40 | }
41 | finally
42 | {
43 | main?.Dispose();
44 | }
45 | #endif
46 |
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Resources/Icons/Guardian.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/Guardian.ico
--------------------------------------------------------------------------------
/src/Resources/Icons/arrow-down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/arrow-down.png
--------------------------------------------------------------------------------
/src/Resources/Icons/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/arrow-left.png
--------------------------------------------------------------------------------
/src/Resources/Icons/arrow-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/arrow-right.png
--------------------------------------------------------------------------------
/src/Resources/Icons/arrow-up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/arrow-up.png
--------------------------------------------------------------------------------
/src/Resources/Icons/zoom-in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/zoom-in.png
--------------------------------------------------------------------------------
/src/Resources/Icons/zoom-out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Icons/zoom-out.png
--------------------------------------------------------------------------------
/src/Resources/Images/OnGuard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Images/OnGuard.jpg
--------------------------------------------------------------------------------
/src/Resources/Images/OnGuardNoPictures.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Images/OnGuardNoPictures.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street1.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street2.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street3.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street4.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street5.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street6.jpg
--------------------------------------------------------------------------------
/src/Resources/Samples/Street7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ken98045/On-Guard/74fe7f071a6a1afff81dec2dec69f0644ce3fa2f/src/Resources/Samples/Street7.jpg
--------------------------------------------------------------------------------
/src/SafeParse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace OnGuardCore
8 | {
9 | // There are a LOT of cases where we are parsing values from various sources, primarily settings
10 | // in these cases we are getting strings and we need to parse them into the approriate type.
11 | // It is generally safe to leave them as the default (but not always which is why we log it)
12 |
13 | public static class SafeParse
14 | {
15 | public static object Parse(Type t, string str)
16 | {
17 | object o = null;
18 |
19 | try
20 | {
21 | if (!string.IsNullOrEmpty(str))
22 | {
23 |
24 | if (t.BaseType.Name == "Enum")
25 | {
26 | o = 0;
27 | object ee = Enum.Parse(t, str);
28 | o = ee;
29 | }
30 | else
31 | {
32 |
33 | switch (t.Name)
34 | {
35 | case "Int32":
36 | o = 0;
37 | int ii = int.Parse(str);
38 | o = ii;
39 | break;
40 |
41 | case "Double":
42 | o = 0.0;
43 | double dd = double.Parse(str);
44 | o = dd;
45 | break;
46 |
47 | case "Boolean":
48 | o = false;
49 | object oo = bool.Parse(str);
50 | o = oo;
51 | break;
52 |
53 | case "Guid":
54 | o = Guid.Empty;
55 | Guid gg = Guid.Parse(str);
56 | o = gg;
57 | break;
58 |
59 | default:
60 | o = null;
61 | break;
62 |
63 | }
64 | }
65 | }
66 | else
67 | {
68 |
69 | if (t.BaseType.Name == "Enum")
70 | {
71 | o = 0; // a reasonable default?
72 | }
73 | else
74 | {
75 |
76 | switch (t.Name)
77 | {
78 | case "Int32":
79 | o = 0;
80 | break;
81 |
82 | case "Double":
83 | o = 0.0;
84 | break;
85 |
86 | case "Boolean":
87 | o = false;
88 | break;
89 |
90 | case "Guid":
91 | o = Guid.Empty;
92 | break;
93 |
94 | default:
95 | o = null;
96 | break;
97 |
98 | }
99 | }
100 |
101 | }
102 | }
103 | catch (Exception ex)
104 | {
105 | Dbg.Write(LogLevel.Error, "SafeParse - Unexpected exception: " + ex.Message);
106 | }
107 |
108 | return o;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/Storage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 | using OnGuardCore.Src.Properties;
8 | using System.Windows.Forms;
9 | using Microsoft.Win32;
10 | using System.Drawing;
11 |
12 | namespace OnGuardCore
13 | {
14 | public class Storage
15 | {
16 | private static IStorage _xmlStore = new XMLStorage();
17 | Storage()
18 | {
19 |
20 | }
21 |
22 | public static bool DoesDataDirectoryExist()
23 | {
24 | bool result = false;
25 |
26 | string path = Settings.Default.DataFileLocation;
27 | if (Directory.Exists(path))
28 | {
29 | result = true;
30 | }
31 | return result;
32 | }
33 |
34 | public static bool DoesSettingsFileExist()
35 | {
36 | bool result = false;
37 |
38 | if (DoesDataDirectoryExist())
39 | {
40 | string path = GetFilePath("OnGuardStorage.xml");
41 | if (File.Exists(path))
42 | {
43 | result=true;
44 | }
45 | }
46 |
47 | return result;
48 | }
49 |
50 | static public string GetFilePath(string fileName)
51 | {
52 | string path = Settings.Default.DataFileLocation;
53 | if (string.IsNullOrEmpty(path))
54 | {
55 | using OnGuardDataDialog dlg = new ();
56 | if (DialogResult.OK == dlg.ShowDialog())
57 | {
58 | path = dlg.FolderLocation;
59 | Settings.Default.DataFileLocation = path;
60 | Settings.Default.DatabaseFileLocation = dlg.DatabaseFolderLocation;
61 | Settings.Default.Save();
62 | }
63 | else
64 | {
65 | MessageBox.Show("You must set a data file folder. The application will now exit", "Exiting!");
66 | Application.Exit();
67 | }
68 | }
69 |
70 | if (!Directory.Exists(path))
71 | {
72 | Directory.CreateDirectory(path);
73 | }
74 |
75 | if (!string.IsNullOrEmpty(fileName))
76 | {
77 | path = Path.Combine(path, fileName);
78 | }
79 |
80 | return path;
81 | }
82 |
83 |
84 | public static IStorage Instance
85 | {
86 | get
87 | {
88 | return _xmlStore;
89 | }
90 | }
91 |
92 | }
93 |
94 |
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/src/TimeTrigger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace OnGuardCore
9 | {
10 | public delegate void GuidDelegate(Guid id);
11 | public class TimeTrigger
12 | {
13 | static Dictionary _timers = new Dictionary();
14 | public static event GuidDelegate OnTimeTriggered = delegate { };
15 |
16 | // The trigger passed in is not a full date/time.
17 | // Rather, it is a time such as 4:46pm where the time might be today/tomorrow -- we ignore the year/month/day/seconds
18 | public static void AddTimer(DateTime trigger, Guid id)
19 | {
20 | DateTime now = DateTime.Now;
21 |
22 | // Get some easy comparison for the requested vs now.
23 | int totalNowMin = (now.Hour * 60) + now.Minute;
24 | int totalTriggerMin = (trigger.Hour * 60) + trigger.Minute;
25 | DateTime realTrigger = now;
26 |
27 | if (totalNowMin >= totalTriggerMin)
28 | {
29 | // we are dealing with tomorrow, not today
30 | realTrigger = new DateTime(now.Year, now.Month, now.Day, trigger.Hour, trigger.Minute, 0);
31 | realTrigger = realTrigger.AddDays(1);
32 | }
33 | else
34 | {
35 | realTrigger = new DateTime(now.Year, now.Month, now.Day, trigger.Hour, trigger.Minute, 0); // today
36 | }
37 |
38 | TimeSpan span = realTrigger - now;
39 |
40 | Timer timer = new Timer(OnTimer, id, span, TimeSpan.FromMilliseconds(-1));
41 | _timers[id] = timer;
42 |
43 | }
44 |
45 |
46 | private static void OnTimer(object obj)
47 | {
48 | Guid id = (Guid)obj;
49 | OnTimeTriggered(id);
50 | _timers[id].Change(TimeSpan.FromDays(1), TimeSpan.FromMilliseconds(-1)); // reset for tomorrow
51 | }
52 |
53 | public static void Remove(Guid id)
54 | {
55 | if (_timers.ContainsKey(id))
56 | {
57 | Timer t = _timers[id];
58 | t.Dispose();
59 | _timers.Remove(id);
60 | }
61 |
62 | }
63 |
64 | public static void ClearAll()
65 | {
66 | foreach (var timer in _timers.Values)
67 | {
68 | timer.Dispose();
69 | }
70 |
71 | _timers.Clear();
72 | }
73 |
74 | public static DateTime GetHourMinute(int hour, int minute)
75 | {
76 | DateTime newDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, minute, 0);
77 | return newDate;
78 | }
79 | }
80 |
81 | }
--------------------------------------------------------------------------------
/src/TimerPlus.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace OnGuardCore
4 | {
5 |
6 | public class TimerPlus : System.Timers.Timer
7 | {
8 | private DateTime m_dueTime;
9 |
10 | public TimerPlus() : base()
11 | {
12 | this.Elapsed += this.ElapsedAction;
13 | }
14 |
15 | protected new void Dispose()
16 | {
17 | this.Elapsed -= this.ElapsedAction;
18 | base.Dispose();
19 | }
20 |
21 | public double TimeLeft
22 | {
23 | get
24 | {
25 | return (this.m_dueTime - DateTime.Now).TotalMilliseconds;
26 | }
27 | }
28 |
29 | public new void Start()
30 | {
31 | this.m_dueTime = DateTime.Now.AddMilliseconds(this.Interval);
32 |
33 | base.Start();
34 | }
35 |
36 | private void ElapsedAction(object sender, System.Timers.ElapsedEventArgs e)
37 | {
38 | if (this.AutoReset)
39 | {
40 | this.m_dueTime = DateTime.Now.AddMilliseconds(this.Interval);
41 | }
42 | }
43 | }
44 |
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/WaitCursor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 |
8 | namespace OnGuardCore
9 | {
10 | public class WaitCursor : IDisposable
11 | {
12 | Cursor m_cursorOld;
13 | bool _disposedValue = false; // To detect redundant call
14 |
15 | ///
16 | /// .cteur
17 | ///
18 | public WaitCursor()
19 | {
20 | m_cursorOld = Cursor.Current;
21 | Cursor.Current = Cursors.WaitCursor;
22 | }
23 |
24 | ///
25 | /// Dispose
26 | ///
27 | public void Dispose()
28 | {
29 | Dispose(true);
30 | GC.SuppressFinalize(this);
31 | }
32 |
33 |
34 | ///
35 | /// Dispose
36 | ///
37 | ///
38 | protected virtual void Dispose(bool disposing)
39 | {
40 | if (!_disposedValue)
41 | {
42 | Cursor.Current = m_cursorOld;
43 | Cursor.Position = Cursor.Position; // force update
44 | }
45 | _disposedValue = true;
46 | }
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------