diff --git a/AIS/AISAdmin/AISAdmin.csproj b/AIS/AISAdmin/AISAdmin.csproj
index 1dd8d2dd..4fefaadd 100644
--- a/AIS/AISAdmin/AISAdmin.csproj
+++ b/AIS/AISAdmin/AISAdmin.csproj
@@ -9,10 +9,14 @@
+
+
+
+
@@ -26,10 +30,14 @@
+
+
+
+
diff --git a/AIS/AISAdmin/Main.Designer.cs b/AIS/AISAdmin/Main.Designer.cs
index e97243a3..7864f6d3 100644
--- a/AIS/AISAdmin/Main.Designer.cs
+++ b/AIS/AISAdmin/Main.Designer.cs
@@ -43,9 +43,16 @@
this.listBoxZones = new System.Windows.Forms.ListBox();
this.buttonImportZone = new System.Windows.Forms.Button();
this.groupBoxAssignments = new System.Windows.Forms.GroupBox();
+ this.listBoxTargets = new System.Windows.Forms.ListBox();
+ this.buttonAssignSelectedTarget = new System.Windows.Forms.Button();
+ this.buttonDeleteAssignment = new System.Windows.Forms.Button();
+ this.buttonNewAssignment = new System.Windows.Forms.Button();
+ this.listBoxAssignment = new System.Windows.Forms.ListBox();
this.textBoxGroup = new System.Windows.Forms.TextBox();
this.buttonSaveGroup = new System.Windows.Forms.Button();
+ this.label2 = new System.Windows.Forms.Label();
this.groupBoxZones.SuspendLayout();
+ this.groupBoxAssignments.SuspendLayout();
this.SuspendLayout();
//
// label1
@@ -193,6 +200,12 @@
//
// groupBoxAssignments
//
+ this.groupBoxAssignments.Controls.Add(this.label2);
+ this.groupBoxAssignments.Controls.Add(this.listBoxTargets);
+ this.groupBoxAssignments.Controls.Add(this.buttonAssignSelectedTarget);
+ this.groupBoxAssignments.Controls.Add(this.buttonDeleteAssignment);
+ this.groupBoxAssignments.Controls.Add(this.buttonNewAssignment);
+ this.groupBoxAssignments.Controls.Add(this.listBoxAssignment);
this.groupBoxAssignments.Location = new System.Drawing.Point(12, 235);
this.groupBoxAssignments.Name = "groupBoxAssignments";
this.groupBoxAssignments.Size = new System.Drawing.Size(776, 203);
@@ -200,6 +213,60 @@
this.groupBoxAssignments.TabStop = false;
this.groupBoxAssignments.Text = "Assignments";
//
+ // listBoxTargets
+ //
+ this.listBoxTargets.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.listBoxTargets.Enabled = false;
+ this.listBoxTargets.FormattingEnabled = true;
+ this.listBoxTargets.ItemHeight = 15;
+ this.listBoxTargets.Location = new System.Drawing.Point(401, 37);
+ this.listBoxTargets.Name = "listBoxTargets";
+ this.listBoxTargets.Size = new System.Drawing.Size(369, 154);
+ this.listBoxTargets.TabIndex = 7;
+ //
+ // buttonAssignSelectedTarget
+ //
+ this.buttonAssignSelectedTarget.Enabled = false;
+ this.buttonAssignSelectedTarget.Image = global::AISAdmin.Properties.Resources.delete;
+ this.buttonAssignSelectedTarget.Location = new System.Drawing.Point(358, 111);
+ this.buttonAssignSelectedTarget.Name = "buttonAssignSelectedTarget";
+ this.buttonAssignSelectedTarget.Size = new System.Drawing.Size(37, 31);
+ this.buttonAssignSelectedTarget.TabIndex = 6;
+ this.buttonAssignSelectedTarget.UseVisualStyleBackColor = true;
+ //
+ // buttonDeleteAssignment
+ //
+ this.buttonDeleteAssignment.Enabled = false;
+ this.buttonDeleteAssignment.Image = global::AISAdmin.Properties.Resources.delete;
+ this.buttonDeleteAssignment.Location = new System.Drawing.Point(358, 74);
+ this.buttonDeleteAssignment.Name = "buttonDeleteAssignment";
+ this.buttonDeleteAssignment.Size = new System.Drawing.Size(37, 31);
+ this.buttonDeleteAssignment.TabIndex = 5;
+ this.buttonDeleteAssignment.UseVisualStyleBackColor = true;
+ //
+ // buttonNewAssignment
+ //
+ this.buttonNewAssignment.Image = global::AISAdmin.Properties.Resources.document_plain_new;
+ this.buttonNewAssignment.Location = new System.Drawing.Point(358, 37);
+ this.buttonNewAssignment.Name = "buttonNewAssignment";
+ this.buttonNewAssignment.Size = new System.Drawing.Size(37, 31);
+ this.buttonNewAssignment.TabIndex = 3;
+ this.buttonNewAssignment.UseVisualStyleBackColor = true;
+ //
+ // listBoxAssignment
+ //
+ this.listBoxAssignment.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)));
+ this.listBoxAssignment.Enabled = false;
+ this.listBoxAssignment.FormattingEnabled = true;
+ this.listBoxAssignment.ItemHeight = 15;
+ this.listBoxAssignment.Location = new System.Drawing.Point(6, 37);
+ this.listBoxAssignment.Name = "listBoxAssignment";
+ this.listBoxAssignment.Size = new System.Drawing.Size(346, 154);
+ this.listBoxAssignment.TabIndex = 1;
+ //
// textBoxGroup
//
this.textBoxGroup.Location = new System.Drawing.Point(335, 11);
@@ -219,6 +286,15 @@
this.buttonSaveGroup.UseVisualStyleBackColor = true;
this.buttonSaveGroup.Click += new System.EventHandler(this.buttonSaveGroup_Click);
//
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(7, 19);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(286, 15);
+ this.label2.TabIndex = 8;
+ this.label2.Text = "Assignment will be to all zones in the selected group!";
+ //
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@@ -240,6 +316,8 @@
this.Load += new System.EventHandler(this.Main_Load);
this.groupBoxZones.ResumeLayout(false);
this.groupBoxZones.PerformLayout();
+ this.groupBoxAssignments.ResumeLayout(false);
+ this.groupBoxAssignments.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -263,5 +341,11 @@
private Button buttonEditZone;
private Button buttonImportZone;
private CheckBox checkBoxZoneActive;
+ private ListBox listBoxTargets;
+ private Button buttonAssignSelectedTarget;
+ private Button buttonDeleteAssignment;
+ private Button buttonNewAssignment;
+ private ListBox listBoxAssignment;
+ private Label label2;
}
}
\ No newline at end of file
diff --git a/AIS/AISAdmin/Main.cs b/AIS/AISAdmin/Main.cs
index ebaa41b2..a6539779 100644
--- a/AIS/AISAdmin/Main.cs
+++ b/AIS/AISAdmin/Main.cs
@@ -9,6 +9,8 @@ namespace AISAdmin
private AIS_SQLiteStorage? _storage;
private BindingList? _monitorGroups = new();
private MonitorGroup? _currentGroup;
+ private Dictionary> _zoneAssignmentDict = new();
+ private List _allTargets = new();
public Main()
{
@@ -108,7 +110,7 @@ namespace AISAdmin
}
}
- private void Main_Load(object sender, EventArgs e)
+ private async void Main_Load(object sender, EventArgs e)
{
_storage = new AIS_SQLiteStorage(null);
_monitorGroups = new BindingList(_storage.LoadGroups());
@@ -127,6 +129,12 @@ namespace AISAdmin
this.comboBoxGroup.SelectedIndex = 0;
this.buttonSaveGroup.Enabled = _monitorGroups.Count > 0;
this.listBoxZones.Enabled = _monitorGroups.Count > 0;
+
+ Dictionary allTargets = await _storage.LoadTargets();
+ foreach (int mmsi in allTargets.Keys)
+ this._allTargets.Add(allTargets[mmsi]);
+ this._allTargets.Sort();
+ this.listBoxTargets.DataSource = this._allTargets;
}
private void comboBoxGroup_SelectedIndexChanged(object sender, EventArgs e)
@@ -136,6 +144,10 @@ namespace AISAdmin
{
_currentGroup.Zones.Sort();
this.listBoxZones.DataSource = new BindingList(_currentGroup.Zones);
+ foreach(MonitorZone zone in _currentGroup.Zones)
+ {
+ _zoneAssignmentDict[zone] = _storage?.LoadAssignmentsForZone(zone.Id) ?? new();
+ }
}
else
{
@@ -164,6 +176,7 @@ namespace AISAdmin
{
this.checkBoxZoneActive.Checked = mz.Active;
this.textBoxZone.Text = mz.Name;
+ this.listBoxAssignment.DataSource = new BindingList(this._zoneAssignmentDict[mz]);
}
}
}
diff --git a/AIS/ReadMe.md b/AIS/ReadMe.md
index 90f81744..b5bdde1d 100644
--- a/AIS/ReadMe.md
+++ b/AIS/ReadMe.md
@@ -8,6 +8,25 @@ ___

+### Web - "Laufzettel"
+
+In der Übersicht nur Daten aus der Datenbank, vorerst keine Daten aus Wetris.
+
+Überlegungen:
+
+- Wie können ein- bzw. ausgehende Schiffe erkannt werden?
+ - Nach "langer" Zeit wird ein Alarm im "Randgebiet" erkannt. Je nach Anfang/Ende ist es ein eingehender oder ausgehender Anlauf.
+- Muss ein Anlauf getrackt werden oder reicht eine "Menge" an Alarmen?
+ - Das Datenmodell muss den Anlauf vermutlich abbilden, aber in der DB reichen vermutlich die Alarme.
+- Wann erreicht ein Schiff die Zone? (aka, wann wird der Alarm ausgelöst)
+ - kein aktueller Alarm für die Zone __und__
+ - Die Position wird bereits für n Sekunden innerhalb der Zone reported (avoid jitter)
+- Im Alarm muss gespeichert werden, wann
+ 1) die Zone "zuerst" erreicht wurde
+ 2) der Zeitpunkt des letzten Reports innerhalb der Zone
+ 3) keine Referenz sondern Kopie der Position/Timestamp?
+ - Alarm / Zuordnung sind unabhängig von der Gruppe. Die Gruppe / der Zulauf ergibt sich erst in der Webanwendung. (Ist das sinnvoll?)
+
## Stand Dez 22
Nächste geplante Schritte:
diff --git a/AIS/bsmd.AIS2Service/AIS_SQLiteStorage.cs b/AIS/bsmd.AIS2Service/AIS_SQLiteStorage.cs
index a586dff4..9eaa2a77 100644
--- a/AIS/bsmd.AIS2Service/AIS_SQLiteStorage.cs
+++ b/AIS/bsmd.AIS2Service/AIS_SQLiteStorage.cs
@@ -291,6 +291,68 @@ namespace bsmd.AIS2Service
return insertedRows == 1;
}
+ public List LoadVerticesForZone(long zoneId)
+ {
+ List vertices = new List();
+ string loadVerticesString = "SELECT id, monitor_zone_id, latitude, longitude FROM zone_vertex WHERE monitor_zone_id = @ID";
+ SQLiteCommand laCmd = new SQLiteCommand(loadVerticesString, _connection);
+ laCmd.Parameters.AddWithValue("@ID", zoneId);
+ SQLiteDataReader reader = laCmd.ExecuteReader();
+ if (reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ long id = reader.GetInt64(0);
+ GeoPoint gp = new GeoPoint(id);
+ gp.MonitorZoneId = reader.GetInt64(1);
+ gp.Lat = reader.GetDouble(2);
+ gp.Lon = reader.GetDouble(3);
+ vertices.Add(gp);
+ }
+ reader.Close();
+ }
+ laCmd.Dispose();
+ return vertices;
+ }
+
+ #endregion
+
+ #region MonitorAssignment
+
+ public bool Save(MonitorAssignment assignment)
+ {
+ if (assignment == null) return false;
+ string saveGeoPointString = $"INSERT INTO zone_assignment (mmsi, monitor_zone_id, type) VALUES ({assignment.MMSI}, {assignment.MonitorZoneId}, {assignment.MonitorType})";
+ SQLiteCommand cmd = new SQLiteCommand(saveGeoPointString, _connection);
+ int insertedRows = cmd.ExecuteNonQuery();
+ cmd.Dispose();
+ return insertedRows == 1;
+ }
+
+ public List LoadAssignmentsForZone(long zoneId)
+ {
+ List assignments = new List();
+ string loadAssignmentsString = "SELECT za.id, za.mmsi, za.monitor_zone_id, za.type FROM zone_assigment za WHERE za.monitor_zone_id = @ID";
+ SQLiteCommand laCmd = new SQLiteCommand(loadAssignmentsString, _connection);
+ laCmd.Parameters.AddWithValue("@ID", zoneId);
+ SQLiteDataReader reader = laCmd.ExecuteReader();
+ if (reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ long id = reader.GetInt64(0);
+ MonitorAssignment ma = new MonitorAssignment(id);
+ ma.MMSI = reader.GetInt32(1);
+ ma.MonitorZoneId = reader.GetInt64(2);
+ ma.MonitorType = (MonitorAssignment.ZoneMonitorType)reader.GetInt32(3);
+ assignments.Add(ma);
+ }
+ reader.Close();
+ }
+ laCmd.Dispose();
+ return assignments;
+ }
+
#endregion
#endregion
diff --git a/AIS/bsmd.AIS2Service/AIS_Target.cs b/AIS/bsmd.AIS2Service/AIS_Target.cs
index 9f1f698b..71b71626 100644
--- a/AIS/bsmd.AIS2Service/AIS_Target.cs
+++ b/AIS/bsmd.AIS2Service/AIS_Target.cs
@@ -3,7 +3,7 @@ using System.Data;
namespace bsmd.AIS2Service
{
- public class AIS_Target
+ public class AIS_Target : IComparable
{
#region private members
@@ -351,5 +351,14 @@ namespace bsmd.AIS2Service
#endregion
+ #region IComparable implementation
+
+ public int CompareTo(AIS_Target other)
+ {
+ return this.Name.CompareTo(other.Name);
+ }
+
+ #endregion
+
}
}
diff --git a/AIS/bsmd.AIS2Service/MonitorZone.cs b/AIS/bsmd.AIS2Service/MonitorZone.cs
index 3e67d1e4..36f1bda0 100644
--- a/AIS/bsmd.AIS2Service/MonitorZone.cs
+++ b/AIS/bsmd.AIS2Service/MonitorZone.cs
@@ -3,16 +3,13 @@
// Description: Represents a geographical area that should be checked against
// ship positions
+using log4net;
+
using System;
using System.Collections.Generic;
-using System.Drawing;
using System.IO;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Web.UI.WebControls;
using System.Xml.Linq;
-using log4net;
namespace bsmd.AIS2Service
{
@@ -278,6 +275,13 @@ namespace bsmd.AIS2Service
public ZoneMonitorType MonitorType { get; set; } = ZoneMonitorType.INACTIVE;
+ public long MonitorZoneId { get; set; }
+
+ public override string ToString()
+ {
+ return String.Format("{0} {1}", MMSI, MonitorType);
+ }
+
}
#endregion