diff --git a/chasemapper/__init__.py b/chasemapper/__init__.py
index 03e9cb7..4226042 100644
--- a/chasemapper/__init__.py
+++ b/chasemapper/__init__.py
@@ -8,4 +8,4 @@
# Now using Semantic Versioning (https://semver.org/) MAJOR.MINOR.PATCH
-__version__ = "1.3.1"
+__version__ = "1.3.2"
diff --git a/chasemapper/bearings.py b/chasemapper/bearings.py
index 221bb35..810c8fb 100644
--- a/chasemapper/bearings.py
+++ b/chasemapper/bearings.py
@@ -44,6 +44,8 @@ class Bearings(object):
# }
self.bearings = {}
+ self.bearing_sources = []
+
self.bearing_lock = Lock()
# Internal record of the chase car position, which is updated with incoming GPS data.
@@ -183,6 +185,10 @@ class Bearings(object):
"source": _source,
}
+ # Allow override of the heading valid calculations if a hearing_override field is supplied
+ if "heading_override" in bearing:
+ _new_bearing["heading_valid"] = bearing["heading_override"]
+
elif bearing["bearing_type"] == "absolute":
# Absolute bearing - use the provided data as-is
@@ -213,6 +219,10 @@ class Bearings(object):
self.bearings["%.4f" % _arrival_time] = _new_bearing
+ if _source not in self.bearing_sources:
+ self.bearing_sources.append(_source)
+ logging.info(f"Bearing Handler - New source of bearings: {_source}")
+
# Now we need to do a clean-up of our bearing list.
# At this point, we should always have at least 2 bearings in our store
if len(self.bearings) == 1:
diff --git a/static/js/bearings.js b/static/js/bearings.js
index 8b64125..5c6e926 100644
--- a/static/js/bearings.js
+++ b/static/js/bearings.js
@@ -15,6 +15,8 @@
var bearing_store = {};
+var bearing_sources = [];
+
var bearings_on = true;
var bearings_only_mode = false;
@@ -67,6 +69,7 @@ function destroyAllBearings(){
});
bearing_store = {};
+ bearing_sources = [];
}
@@ -86,6 +89,11 @@ function bearingValid(bearing){
}
}
+ // Disable showing of this bearing if the source is not selected
+ if (!document.getElementById("bearing_source_" + bearing.source).checked){
+ _show_bearing = false;
+ }
+
return _show_bearing;
}
@@ -106,6 +114,18 @@ function addBearing(timestamp, bearing, live){
bearing_store[timestamp] = bearing;
+ if ( !bearing_sources.includes(bearing.source)){
+ bearing_sources.push(bearing.source);
+ _new_bearing_div_name = "bearing_source_" + bearing.source;
+ bearing_sources_div = "
Source: " + bearing.source + "
";
+ $("#bearing_source_selector").append(bearing_sources_div);
+ $("#"+_new_bearing_div_name).prop('checked',true);
+
+ $("#"+_new_bearing_div_name).change(function(){
+ redrawBearings();
+ });
+ }
+
// Calculate the end position.
var _end = calculateDestination(L.latLng([bearing_store[timestamp].lat, bearing_store[timestamp].lon]), bearing_store[timestamp].true_bearing, bearing_length);
diff --git a/templates/index.html b/templates/index.html
index 86fbd5b..ffcb1e3 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -898,7 +898,6 @@
Show Stationary Bearings
-
@@ -906,6 +905,9 @@
+
Bearing Sources
+
+
Bearing Style
Bearing Length (km)
diff --git a/utils/bearing_o_clock.py b/utils/bearing_o_clock.py
new file mode 100644
index 0000000..fa6d3bd
--- /dev/null
+++ b/utils/bearing_o_clock.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# ChaseMapper - Bearing o'Clock
+#
+# Add bearings based on O'Clock position (1 through 12)
+# Run with: python bearing_o_clock.py bearing_source_name
+#
+# Copyright (C) 2019 Mark Jessop
+# Released under GNU GPL v3 or later
+#
+#
+import json
+import socket
+import sys
+import time
+import datetime
+import traceback
+
+
+def send_relative_bearing(bearing, source, heading_override=False, udp_port=55672):
+ """
+ Send a basic relative bearing
+ """
+ packet = {
+ 'type' : 'BEARING',
+ 'bearing' : bearing,
+ 'bearing_type': 'relative',
+ 'source': source
+ }
+
+ if heading_override:
+ packet["heading_override"] = True
+
+ # Set up our UDP socket
+ s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ s.settimeout(1)
+ # Set up socket for broadcast, and allow re-use of the address
+ s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ try:
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
+ except:
+ pass
+ s.bind(('',udp_port))
+ try:
+ s.sendto(json.dumps(packet).encode('ascii'), ('', udp_port))
+ except socket.error:
+ s.sendto(json.dumps(packet).encode('ascii'), ('127.0.0.1', udp_port))
+
+
+if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ _source = sys.argv[1]
+ else:
+ _source = "o_clock_entry"
+
+ try:
+ while True:
+
+ print("Enter O-Clock Bearing (1-12):")
+ _val = input()
+
+ try:
+ _val_int = int(_val)
+
+ _bearing = (_val_int%12)*30
+
+ print(f"Sending Relative Bearing: {_bearing}")
+
+ send_relative_bearing(_bearing, _source, heading_override=True)
+ except Exception as e:
+ print(f"Error handling input: {str(e)}")
+ except KeyboardInterrupt:
+ sys.exit(0)
+
+