Geofencing

From Maria GDK Wiki
Jump to navigation Jump to search

Geofencing allows the user to define geographical shapes that acts as virtual "fences". By defining interaction rules, it is possible to generate events based on how tracks interact with these shapes.

General

Geofencingserviceoverview.png

A geofence consists of the following components:

  • A geographical shape. Various object types are supported, for instance lines, polygon areas, sectors and range circles
  • Interaction type, one of entering, leaving or crossing
  • Track filter
  • Report template

When a track interacts with a geofence in accordance with a rule, a report is generated. A report template determines the contents of the report. Typically, the report includes:

  • Time of interaction
  • Track details
  • Shape/object details
  • Static information contained in the template, for instance textual warnings and importance of the event

The core geofencing component is the geofencing service. It is responsible for fetching tracks and fence objects from respective services, for handling rule setup and execution as well as for providing clients with events.

Rules by default apply to all tracks and shapes/objects in the service. Take care to define filters that only include the desired combination of tracks and shapes.

This example was generated using recorded AIS data and sample symbology. Notifications are displayed using the geofencing service diagnostic application.

Track entering Langesund area
Notification details


Datasources

Geofencingdatasourceoverview.png

Data sources are set up using the IDataManagerServiceBase interface.

Each data source entry causes the geo fencing service to fetch data from that source. One data source refers to a tracklist within a specified service or to a draw object list within a single draw object service.

Note that tracks and objects are fetched at preset intervals and are not synchronized to track updates or draw object updates. By using versioning/generations, only changed tracks or draw objects are fetched.

The geofencing service is responsible for handling cases where the data sources are temporarily unavailable, for instance if a source service is restarted.


Rules

Rules define the circumstances that are required in order to trigger a geofencing event. In addition, a rule contains the information used to create the contents of the geofencing event.

Geofencingruleexecution.png

Rules are added through IGeoFencingRuleServiceBase using the AddRule method:

GeoFenceRuleDef genericRuleDef = new GeoFenceRuleDef();
genericRuleDef.Id = Guid.Parse("{4BB9385F-E2B3-457B-AEF1-5B77950FF9D6}");
genericRuleDef.Actions = new List<ActionBaseDef> { 
  new NotificationActionDef { NotificationTemplate = template } };
genericRuleDef.Interactions = 
  GeoFenceInteractions.Entering | 
  GeoFenceInteractions.Leaving |
  GeoFenceInteractions.Crossing;
genericRuleDef.GeoFenceConditionXml = 
  @"<fieldcondition op=""Eq"" field=""TriggerCode"" value=""1""/>";

fenceRuleServiceClient.AddRule(genericRuleDef);

Interactions

Interactions can be "Entering", "Leaving", "Crossing" or "Appearing". When defining a rule, one or more interaction types can be combined using flags/bitwise or.

"Entering" and "Leaving"

A track is considered "Entering" a shape if the previous position was outside of the object and the current position is inside the object. "Leaving" occurs when previous position was inside the shape, and current position is outside of the shape. "Entering" and "Leaving" are only defined for objects with an area, it does not apply to line type shapes without a buffer.

Entering occurs only when both current and previous positions are defined. The same goes for leaving

"Crossing"

A track is considering "Crossing" a shape if the geodesic line between previous and current position intersects an odd number of line segments of the shape. "Crossing" is only defined for line type objects, and is not valid for objects with an area. By monitoring "Entering" and "Leaving" type of interactions for a single track, a client can easily implement "Crossing" type events for shapes with area.

"Appearing"

A track is considering "Appearing" inside an area type shape if the track appears inside the object with no previous positions available.

Filters

Filters in a rule are used to connect a rule to a set of shapes and tracks. By default a rule applies to all tracks and shapes in the system. The example above contains the following filter:

genericRuleDef.GeoFenceConditionXml = 
  @"<fieldcondition op=""Eq"" field=""TriggerCode"" value=""1""/>";

This filter causes the rule to only consider shapes with the field "TriggerCode" set to "1". This allows setup of a single, generic rule that is only triggered for selected shapes.\ \ These filters are defined in the same way as track/draw object styling filters. Complex filters can be created by using nested conditions:

<compositecondition op="Or">
  <speedcondition value="0kts" op="Eq"/>
  <speedcondition value="" op="Undefined"/>     
</compositecondition>
Rules are very loosely connected to tracks and geo shapes. In order to create 1:1 connections to either a track or a shape, the corresponding filter must reference a unique property or a unique combination of properties of the track or shape, for instance the track id or object id.

Templates

Templates define the contents of the report/event that is generated.

var template = new NotificationTemplateDef();
template.Heading = "[track.name]([track.type]) [interaction] [shape.Name]";
template.TrackFields.AddRange(new[] { "name", "type", "identity" });
template.GeoShapeFields.AddRange(new[] { "Name" });

In this example, the template generates a report heading by referencing fields in the track and shape that generated the event. This allows for generic templates. The event above might generate the event heading: "M/F Petter Wessel entering Langesund". Any text of the type [track.<field>] is replaced with the responding track field. [shape.<field>] is replaced with the contents of the corresponding shape field. Only fields included in the template TrackFields and GeoShapeFields can be referenced in this manner. In the above example, the following statement allows references to the track fields [track.name], [track.type] and [track.identity]:

template.TrackFields.AddRange(new[] { "name", "type", "identity" });

Note that defining these fields in the template requires advance knowledge of the field names actually included in the tracks with the exception of the following, predefined values:

Key Description
[interaction] Interaction type, one of "Entering", "Leaving" or "Crossing"
[level] Notification level, "Low", "Medium" or "High"
[time] UTC time on the format HH:mm:ssZ, 12:23:34Z
[datetime] ISO 8601 utc datetime, 2014-10-28T11:56:58Z
[track.course] Track course in degrees, 0 is north
[track.speed] Track speed in m/s
[track.speedkts] Track speed in knots

Predefined notification values

By design, the notifications are mostly static and cannot be changed. For instance, the track name or the interaction type cannot be changed. However, various user interactions can take place. Example are acknowledging a notification or marking a notification as read. This is done by appending user data messages to the notification. These messages are composed of a user identifier, a field key and a field value. The template can add initial user data messages to the notification. These will be added using the user id "system". More on this in #Notifications

private void AddRuleWithPredefinedValues()
{
  GeoFenceRuleDef r = new GeoFenceRuleDef();

  var template = new NotificationTemplateDef { Heading = 
    "[track.name] [interaction] [shape.Name]" };
  template.TrackFields.AddRange(new[] { "name" });
  template.GeoShapeFields.AddRange(new[] { "Name" });
  template.NotificationLevel = NotificationLevel.Medium;
  
  // Any notification generated based on this rule will contain
  // userdata region=national for user "system"
  template.PredefinedValues.Add(new Tuple`<string, string>`("region","national"));

  r.Id = Guid.Parse("{807821B5-7432-4B23-BBF6-1F3251EC497D}");
  r.Actions = new List`<ActionBaseDef>`{
    new NotificationActionDef { NotificationTemplate = template }};
  r.Interactions = GeoFenceInteractions.Entering | GeoFenceInteractions.Leaving;
  r.GeoFenceConditionXml = 
    @"`<fieldcondition op=""Contains"" field=""Name"" value=""territorialområde""/>`";

  _ruleServiceClient.AddRule(enteringAndLeavingRuleDef);
}

The following filter definitions include notifications generated with the rule above:

<fieldcondition field="userdata/system/region" op="Eq" value="national"/>
<fieldcondition field="userdata/*/region" op="Eq" value="national"/>

Notifications

Notifications are added by the geofencing core when tracks interact with geo shapes according to predefined rules. Clients can read these notifications as well as append specific types of information to the notifications. Notifications are accessed through INotificationHandlingServiceBase.

Reading notifications

Notifications are read using the service method

NotificationQueryResult GetNotifications(string notificationConditionXml, 
                                         int lastKnownGeneration);

All notifications matching filter, with generation newer than lastKnownGeneration are retrieved from the service.

The GeoFencing.Core library contains NotificationStore which can be used for a client side storage of notifications. The service tester app uses this technique.

Filtering

The filtering syntax used in notification filtering, is the same as used for for geofencing rules and for general track/draw object styling. Using "fieldcondition" in combination with "compositecondition" allows creation of powerful notification filters:

var result=notificationClient.GetNotifications(
  @"<fieldcondition op=""Contains"" field=""heading"" value=""Oslo"" />", -1);

The condition xml-string can also be generated by creating the conditions programatically, and then using the WriteCondition-member of ConditionXmlParser:

FieldCondition c=new FieldCondition("track.somefield", "42", FieldOperator.Contains);
string xml=(new ConditionXmlParser()).WriteCondition(c);
var answer=notifications.GetNotifications(xml, -1);

Note that "fieldcondition" for notifications can be used with the following predefined field codes:

Field key Description
id Notification guid
interaction Entering, Leaving or Crossing
trackid Track identifier, unique within a tracklist
tracklistid Tracklist identifier
geoshapeid Geo shape identifier, unique within a geo shape list
geoshapelistid Geo shape list identifier
geofencecondition XML-representation of the geo shape/geo fence filter
trackcondition XML-representation of the track filter
heading Textual header of the notification
description Textual description of the notification
level Notification level, Low, Medium or High
userdata Refers to userdata for the notification. Format: "userdata/<user> or */<key>"
track.<field> Refers to track field. Note that only fields defined in the notification rule can be referenced
shape.<field> Refers to geo shape field. Note that only fields defined in the notification rule can be referenced

Condition interfaces can be found here: ICondition. Use Condition factory to create concrete conditions.

Service notification filtering

Service filters must be written using xml. Some samples:

<compositecondition op="And">
    <compositecondition op="Or">
      <fieldcondition op="NEq" field="level" value="Low" />
      <agecondition value="20.0" op="Lt" />
    </compositecondition>
    <fieldcondition op="NEq" field="userdata/*/state" value="acknowledged" />
  </compositecondition>

This filter extracts notification state not set to acknowledged (for any user). Messages older than 20 seconds with low notification level are not retrieved.

Client side filtering

After retrieving the notification, the client can perform further filtering if required. This can be done using conditions directly:

ICondition cond=new FieldCondition("SomeFieldName", "20", FieldOperator.Lt);
bool satisfied=cond.IsSatisfied(null, someNotification.GeoObjectAdapter);

One usage is for removing old notifications from the client:

// Assume client store containing notifications,
// List`<NotificationDefWrapper>` notifications
var ageCondition=new AgeCondition { Operator = FieldOperator.Gt, Age = 60 }
notificationClient.RemoveAll(a=>ageCondition.IsSatisfied(null,a.GeoObjectAdapter);

Notification user data

User data can be added from the template using SetNotificationUserData.

    notificationClient.SetNotificationUserData(id,
                new UserDataDefinition { Owner = "myself", 
                                        Key = "somefieldid", 
                                        Value = "1234" });

Logging

Notifications can be logged and restored from file. Use SetNotificationLogInformation to specify filetype ("xml" or "json") and filename.

Notifications are continously written to file as they are retrieved. It is also possible to restore old notification-logs using RestoreNotificationLog.

Track to track fences

It is possible to create moving geo fences by adding a moving range object to the geofencing service and associating it with a track. The moving range will then behave in the same manner as other geo shapes, and can be set up to generate notification events by using rules.

var mrd = new MovingRangeDef();
mrd.Id = Guid.Parse("{DCA13C9F-CE36-4B65-8710-313A312B36CC}");
mrd.TrackId = trackId;
mrd.ListId = listId;
mrd.Name = "Simple moving rangering";
mrd.RangeMeters = 1000;
mrd.Fields = new[]
{
  new KeyValuePair`<string, string>`("fencetype", "moving range")
};

_fenceRuleServiceClient.SetRangeObject(mrd);

And a mathcing rule:

var genericRuleDef = new GeoFenceRuleDef();

var template = new NotificationTemplateDef {
  Heading = "[track.name] [interaction] proximity to"+
    "[shape.track.name] ([shape.fencetype])" };
template.TrackFields.AddRange(new[] { "name" });
template.GeoShapeFields.AddRange(new[] { "track.name", "rangename" });
template.NotificationLevel = NotificationLevel.Low;

genericRuleDef.Id = Guid.Parse("{4BB9385F-E2B3-457B-AEF1-5B77950FF9D8}");
genericRuleDef.NotificationTemplate = template;
genericRuleDef.Interactions = GeoFenceInteractions.Entering;
genericRuleDef.GeoFenceConditionXml = 
  @"`<fieldcondition op=""Eq"" field=""fencetype"" value=""moving range""/>`";

_fenceRuleServiceClient.AddRule(genericRuleDef);

Special considerations

  • Each range object is associated with a single track. If that track is not present, the range ring will not be active
  • A rule that includes the range object must be active, otherwise no notifications will be generated
  • Defining lots of range objects with large ranges has the potential to create very many notifications

Notification template fields

Notification template fields behave the same way for dynamic range objects as for regular shapes, in addition the following replacements are supported:

Key Description
[shape.track.<field>] Refers to trackfield of the track that controls the dynamic range
[track.<field>] Refers to trackfield of the track that enters or leaves the dynamic range
[shape.<field>] Refers to field of the dynamic range

WCF service

The geofencing service is a WCF service that provides core geofencing functionality. The following service interfaces are provided:

Name Description
IDataManagerServiceBase Data source management
IGeoFencingRuleServiceBase Rule management
INotificationHandlingServiceBase Notification handling, including event log and restore

WCF basic http binding is used by default.

Co-hosting with other services is possible in order to reduce the number of required IP ports. On a single user system, co-hosting with track service and draw object service is an option. See Hosting

Deployment and configuration

Service deployment and configuration is decided by the system integrator. Several scenarios are possible:

  • Single geofencing service is used to service all clients. Rule and data source setup is performed by setup/admin function
  • One geofencing service per client. This allows easy setup of personal notifications. Client is responsible for data source and rule setup
  • Multiple services, multiple clients. Each geofencing service produces specific types of notifications. Using multiple data sources allows separation of data sources

Client sample

Use standard WCF app config to connect to one the required interfaces, or connect by using code:

var eaDataManager = new EndpointAddress(
  "http://localhost:9004/GeoFencingService/DataManager");
var b = Binding b = new BasicHttpBinding();
var dataManagerClient = new DataManagerServiceClient(b, eaDataManager);

// In production code where automatic reconnects are required,
// use Connect() instead of ConnectAndWait()
dataManagerClient.ConnectAndWait();
dataManagerClient.GetDataSources();

Service paths for the geofencing interfaces are:

"http://<host>:<port>/GeoFencingService/DataManager"
"http://<host>:<port>/GeoFencingService/FenceRule"
"http://<host>:<port>/GeoFencingService/NotificationHandling"

Geofencing test client

The geofencing test client is distributed with the geofencing service. It can be used to inspect a running geofencing service and perform basic service monitoring.

Testclient.png