diff --git a/README.md b/README.md index c2f32614c53fc20f98bf6fa16a7b4a7dcb153d35..ef8331daaa4c6106493f86446e8216a4d628d500 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ These instructions will get you a copy of the project up and running on your loc Please note that the instructions is not intended to be something that you can follow exactly without any adaptions. See the instructions as initial tips on how the tools can be used, and read the code to get a deeper understanding. -Further down you will find some information how to install trackdirect with Docker and Docker-Compose. +Further down you will find some information how to install trackdirect with Docker and Docker Compose. ### Prerequisites @@ -77,7 +77,7 @@ cd trackdirect Before installing all python requirements it is likly that you need to upgrade pyOpenSSL. ``` sudo python -m easy_install --upgrade pyOpenSSL -`` +``` Install needed python libs ``` @@ -227,31 +227,32 @@ How powerful server you need depends on what type of data source you are going t ## Getting Started - Docker -There is everything prepared to run trackdirect inside of some docker containers. As there is a Docker-Compose file the setup is very simple and fast. +Everything is prepared to run trackdirect inside of docker containers. As there is a Docker Compose file the setup is very simple and fast. -### Install Docker and Docker-Compose -Install [docker](https://docs.docker.com/get-docker/) and [docker-compose](https://docs.docker.com/compose/install/) from the published websites. +### Install Docker and the Docker Compose plugin +Install [Docker and docker-compose-plugin](https://docs.docker.com/engine/install/) as per instructions on their website. ### Config file -Adopt your config in `config/aprsc.conf` and `config/trackdirect.ini`. In `trackdirect.ini` search for 'docker' and change the lines as described in the comments. +Adopt the config in `config/aprsc.conf` and `config/trackdirect.ini`. In `trackdirect.ini` additionally search for 'docker' and change the lines as described in the comments. -### Run Docker-Compose for development containers -To startup trackdirect in an development container run this docker-compose command: +### Run Docker Compose for development containers +To startup trackdirect in a development container run this Docker Compose command: ``` -docker-compose up +docker compose up ``` -If you want to run the container in daemon mode add `-d` to the command. +If you want to run the container in daemon mode (background) add `-d` to the command and use `docker compose logs -f` to watch the output on demand. To stop the containers use `docker compose down`. -### Run Docker-Compose for the last published docker images +### Run Docker Compose for the latest published docker images -@peterus is creating regular docker images from this repository. With the release Docker-Compose file you do not need to install and compile everything by your own. +@peterus is creating regular docker images from this repository. With the release Docker Compose file you don't need to install and compile everything on your own. ``` -docker-compose -f docker-compose-rel.yml up +docker compose -f docker-compose-rel.yml up ``` +This command also accepts `-d` to run as a daemon. ## Contribution Contributions are welcome. Create a fork and make a pull request. Thank you! diff --git a/htdocs/public/css/main.css b/htdocs/public/css/main.css index cdf54dd0f0e9596154e4b1ad3a5eae130bc5c562..ad3bb35d4143d1f6ff611e394caf5bed713be1de 100755 --- a/htdocs/public/css/main.css +++ b/htdocs/public/css/main.css @@ -307,17 +307,20 @@ input[type=submit]:hover { #cordinates-container { clear: both; - padding-top:5px; + padding:5px; color: #4d4d4d; + background-color: rgba(255, 255, 255, 0.7); font-size: 11px; display: none; + min-width: 130px; } #status-container { - padding-top:5px; + padding:5px; white-space:nowrap; line-height: 20px; font-size: 11px; + background-color: rgba(255, 255, 255, 0.7); } @media screen and (min-width: 800px) { diff --git a/htdocs/public/js/trackdirect.min.js b/htdocs/public/js/trackdirect.min.js index dbe8ba199c619815f1091259167e3b1a6fc95754..8bcd1e463f45e759435b7a65d83e45fe1fcaad12 100755 --- a/htdocs/public/js/trackdirect.min.js +++ b/htdocs/public/js/trackdirect.min.js @@ -640,10 +640,10 @@ return(trackdirect.services.distanceCalculator.getDistance(this.getCenterLiteral return 0;};trackdirect.models.Map.prototype._renderCordinatesContainer=function(mouseLatLng){var options=this.getTdMapOptions();if(typeof options.cordinatesContainer==="undefined"){return;} if(options.cordinatesContainer==null){return;} var lat=null;var lng=null;if(typeof mouseLatLng.lat=="function"){lat=mouseLatLng.lat();lng=mouseLatLng.lng();}else{lat=mouseLatLng.lat;lng=mouseLatLng.lng;} -if(lat<=90&&lat>=-90&&lng<=180&&lng>=-180){var content="";content+=this._getGpsDegreeFromGpsDecimal(lat.toFixed(5),"lat");content+=" "+this._getGpsDegreeFromGpsDecimal(lng.toFixed(5),"lon");content+="<br>"+lat.toFixed(5)+", "+lng.toFixed(5);$("#"+options.cordinatesContainer).html(content);}};trackdirect.models.Map.prototype._getGpsDegreeFromGpsDecimal=function(dms,type){var sign=1,Abs=0;var days,minutes,secounds,direction;if(dms<0){sign=-1;} +if(lat<=90&&lat>=-90&&lng<=180&&lng>=-180){var content="";content+=this._getGpsDegreeFromGpsDecimal(lat.toFixed(5),"lat");content+=" "+this._getGpsDegreeFromGpsDecimal(lng.toFixed(5),"lon");content+="<br>"+lat.toFixed(5)+", "+lng.toFixed(5);content+="<br>"+this._getMaidenheadLocatorFromGpsDecimal(lat,lng);$("#"+options.cordinatesContainer).html(content);}};trackdirect.models.Map.prototype._getGpsDegreeFromGpsDecimal=function(dms,type){var sign=1,Abs=0;var days,minutes,secounds,direction;if(dms<0){sign=-1;} Abs=Math.abs(Math.round(dms*1000000));if(type=="lat"&&Abs>90*1000000){return false;}else if(type=="lon"&&Abs>180*1000000){return false;} days=Math.floor(Abs/1000000);minutes=Math.floor((Abs/1000000-days)*60);secounds=((Math.floor(((Abs/1000000-days)*60-minutes)*100000)*60)/ -100000).toFixed();days=days*sign;if(type=="lat")direction=days<0?"S":"N";if(type=="lon")direction=days<0?"W":"E";return days*sign+"º "+minutes+"' "+secounds+"'' "+direction;}; +100000).toFixed();days=days*sign;if(type=="lat")direction=days<0?"S":"N";if(type=="lon")direction=days<0?"W":"E";return days*sign+"º "+minutes+"' "+secounds+"'' "+direction;};trackdirect.models.Map.prototype._getMaidenheadLocatorFromGpsDecimal=function(lat,lng,){const chars='ABCDEFGHIJKLMNOPQRSTUVX';var result='';lng=lng+180;lat=lat+90;result=chars.charAt(parseInt(lng/20));result+=chars.charAt(parseInt(lat/10));result+=parseInt(lng/2%10);result+=parseInt(lat%10);lng_r=(lng-parseInt(lng/2)*2)*60;lat_r=(lat-parseInt(lat))*60;result+=chars.charAt(parseInt(lng_r/5));result+=chars.charAt(parseInt(lat_r/2.5));return result;}; if(typeof google==="object"&&typeof google.maps==="object"){trackdirect.models.Label=function(options,map){this._defaultMap=map;options.map=null;this.setValues(options);this.div_=null;};trackdirect.models.Label.prototype=new google.maps.OverlayView();trackdirect.models.Label.prototype.show=function(){if(typeof this.getMap()==="undefined"||this.getMap()===null){this.setMap(this._defaultMap);}};trackdirect.models.Label.prototype.hide=function(){if(this.getMap()!==null){this.setMap(null);}};trackdirect.models.Label.prototype.onAdd=function(){if(this.div_===null){var jqSpan=$(document.createElement("span"));jqSpan.css("color","#101010");jqSpan.css("text-shadow","1px 1px 1px #FFF, -1px -1px 1px #FFF, 1px -1px 1px #FFF, -1px 1px 1px #FFF, 1px 1px 1px #FFF");jqSpan.css("position","relative");jqSpan.css("top","10px");jqSpan.css("white-space","nowrap");jqSpan.css("font-family","Helvetica");jqSpan.css("font-weight","bold");jqSpan.css("font-size","10px");jqSpan.css("padding","0px");jqSpan.css("z-index","1000");jqSpan.css("margin","0");jqSpan.css("line-height","10px");var span=(this.span_=jqSpan[0]);span.innerHTML=this.get("text").toString();var div=(this.div_=document.createElement("div"));div.appendChild(span);div.style.cssText="position: absolute; display: none";} var pane=this.getPanes().overlayLayer;pane.appendChild(this.div_);var me=this;this.listeners_=[google.maps.event.addListener(this,"position_changed",function(){me.draw();}),google.maps.event.addListener(this,"text_changed",function(){me.draw();}),];};trackdirect.models.Label.prototype.onRemove=function(){if(this.div_!==null&&this.div_.parentNode!==null){this.div_.parentNode.removeChild(this.div_);for(var i=0,I=this.listeners_.length;i<I;++i){google.maps.event.removeListener(this.listeners_[i]);}}};trackdirect.models.Label.prototype.draw=function(){var projection=this.getProjection();if(typeof this.get("position").lat==="function"){var latLng=new google.maps.LatLng({lat:this.get("position").lat(),lng:this.get("position").lng(),});}else{var latLng=new google.maps.LatLng({lat:this.get("position").lat,lng:this.get("position").lng,});} var position=projection.fromLatLngToDivPixel(latLng);var div=this.div_;var span=this.span_;span.innerHTML=this.get("text").toString();div.style.left=position.x+"px";div.style.top=position.y+"px";div.style.display="block";};}else if(typeof L==="object"&&typeof L.Tooltip!=="undefined"){trackdirect.models.Label=function(options,map){this._defaultMap=map;L.Tooltip.call(this,this._getBasicOptions(options));this.setContent(options.text);if(typeof options.position!=="undefined"&&typeof options.position.lat!=="undefined"&&typeof options.position.lng!=="undefined"){this.setLatLng(new L.LatLng(options.position.lat,options.position.lng));}};trackdirect.models.Label.prototype=new L.Tooltip();trackdirect.models.Label.prototype.show=function(){if(!this._defaultMap.hasLayer(this)){this.addTo(this._defaultMap);}};trackdirect.models.Label.prototype.hide=function(){if(this._defaultMap.hasLayer(this)){this._defaultMap.removeLayer(this);}};trackdirect.models.Label.prototype._getBasicOptions=function(options){return{direction:"right",noWrap:true,offset:L.point(2,10),className:"leaflet-marker-labeltext",permanent:true,};};}else if(typeof L==="object"){trackdirect.models.Label=function(options,map){this._defaultMap=map;var position=null;if(typeof options.position!=="undefined"&&typeof options.position.lat!=="undefined"&&typeof options.position.lng!=="undefined"){position=[options.position.lat,options.position.lng];} diff --git a/jslib/src/trackdirect/models/Map.js b/jslib/src/trackdirect/models/Map.js index 931216df81f4ea70cba11b81d3f2c65d4ea6bfa2..47d022192584832bf7ead8fb5a715ebf0c7e849f 100755 --- a/jslib/src/trackdirect/models/Map.js +++ b/jslib/src/trackdirect/models/Map.js @@ -1494,6 +1494,7 @@ trackdirect.models.Map.prototype._renderCordinatesContainer = function ( content += this._getGpsDegreeFromGpsDecimal(lat.toFixed(5), "lat"); content += " " + this._getGpsDegreeFromGpsDecimal(lng.toFixed(5), "lon"); content += "<br>" + lat.toFixed(5) + ", " + lng.toFixed(5); + content += "<br>" + this._getMaidenheadLocatorFromGpsDecimal(lat, lng); $("#" + options.cordinatesContainer).html(content); } @@ -1540,3 +1541,28 @@ trackdirect.models.Map.prototype._getGpsDegreeFromGpsDecimal = function ( //else return value return days * sign + "º " + minutes + "' " + secounds + "'' " + direction; }; + +/** + * Convert decimal gps position to maidenhead locator + * @param {float} lat + * @param {float} lng + * @return {string} + */ +trackdirect.models.Map.prototype._getMaidenheadLocatorFromGpsDecimal = function ( + lat, + lng, +) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVX'; + var result = ''; + lng = lng + 180; + lat = lat + 90; + result = chars.charAt(parseInt(lng / 20)); + result += chars.charAt(parseInt(lat / 10)); + result += parseInt(lng / 2 % 10); + result += parseInt(lat % 10); + lng_r = (lng - parseInt(lng/2)*2) * 60; + lat_r = (lat - parseInt(lat)) * 60; + result += chars.charAt(parseInt(lng_r/5)); + result += chars.charAt(parseInt(lat_r/2.5)); + return result; +}; diff --git a/server/bin/wsserver.py b/server/bin/wsserver.py index 4ad7d1d34a82e265c0fa673dba1d33622090eb8e..890ce097ee02f6ff0859db4b64bf5cc09c220e6a 100644 --- a/server/bin/wsserver.py +++ b/server/bin/wsserver.py @@ -27,9 +27,7 @@ def master(options, trackDirectLogger): trackDirectLogger.warning("Starting master with PID " + str(workerPid) + " (on CPU id(s): " + ','.join(map(str, p.cpu_affinity())) + ")") try: - factory = WebSocketServerFactory( - "ws://" + config.websocketHostname + ":" + str(config.websocketPort), - externalPort = config.websocketExternalPort) + factory = WebSocketServerFactory() factory.protocol = trackdirect.TrackDirectWebsocketServer resource = WebSocketResource(factory) diff --git a/server/trackdirect/repositories/PacketRepository.py b/server/trackdirect/repositories/PacketRepository.py index e9bca1a178389c7f41c3cdd5e55a403bbb8fa450..39380f34f3894e155b3ff6ac63b7fd47ac4d0051 100644 --- a/server/trackdirect/repositories/PacketRepository.py +++ b/server/trackdirect/repositories/PacketRepository.py @@ -372,7 +372,7 @@ class PacketRepository(Repository): sql = sql + \ selectCursor.mogrify( - """order by marker_id desc, id desc limit 1""") + """ order by marker_id desc, id desc limit 1""") # Sort by marker_id first and packet as second, otherwise client might render it wrong selectCursor.execute(sql) @@ -432,7 +432,6 @@ class PacketRepository(Repository): else: return self.create() - def getMostRecentConfirmedObjectListByStationIdList(self, stationIdList, minTimestamp): """Returns an array of the most recent confirmed Packet's specified by station id's