mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
Merge pull request #374 from Freika/fix/gpx-geojson-speed-recording
Fix/gpx geojson speed recording
This commit is contained in:
commit
657f69db44
9 changed files with 253 additions and 32 deletions
|
|
@ -1 +1 @@
|
|||
0.16.0
|
||||
0.16.1
|
||||
|
|
|
|||
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# 0.16.1 - 2024-11-08
|
||||
|
||||
### Fixed
|
||||
|
||||
- Speed is now being recorded into points when a GPX file is being imported. Previously, the speed was not being recorded.
|
||||
- GeoJSON file from GPSLogger now can be imported to Dawarich. Previously, the import was failing due to incorrect parsing of the file.
|
||||
|
||||
### Changed
|
||||
|
||||
- The Vists suggestion job is disabled. It will be re-enabled in the future with a new approach to the visit suggestion process.
|
||||
|
||||
# 0.16.0 - 2024-11-07
|
||||
|
||||
## The Websockets release
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ class Geojson::Params
|
|||
battery: battery_level(feature[:properties][:battery_level]),
|
||||
timestamp: timestamp(feature),
|
||||
altitude: altitude(feature),
|
||||
velocity: feature[:properties][:speed],
|
||||
velocity: speed(feature),
|
||||
tracker_id: feature[:properties][:device_id],
|
||||
ssid: feature[:properties][:wifi],
|
||||
accuracy: feature[:properties][:horizontal_accuracy],
|
||||
accuracy: accuracy(feature),
|
||||
vertical_accuracy: feature[:properties][:vertical_accuracy],
|
||||
raw_data: feature
|
||||
}
|
||||
|
|
@ -50,19 +50,19 @@ class Geojson::Params
|
|||
|
||||
def build_line(feature)
|
||||
feature[:geometry][:coordinates].map do |point|
|
||||
build_line_point(feature, point)
|
||||
build_line_point(point)
|
||||
end
|
||||
end
|
||||
|
||||
def build_multi_line(feature)
|
||||
feature[:geometry][:coordinates].map do |line|
|
||||
line.map do |point|
|
||||
build_line_point(feature, point)
|
||||
build_line_point(point)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_line_point(feature, point)
|
||||
def build_line_point(point)
|
||||
{
|
||||
latitude: point[1],
|
||||
longitude: point[0],
|
||||
|
|
@ -84,7 +84,23 @@ class Geojson::Params
|
|||
def timestamp(feature)
|
||||
return Time.zone.at(feature[3]) if feature.is_a?(Array)
|
||||
|
||||
value = feature.dig(:properties, :timestamp) || feature.dig(:geometry, :coordinates, 3)
|
||||
Time.zone.at(value)
|
||||
value = feature.dig(:properties, :timestamp) ||
|
||||
feature.dig(:geometry, :coordinates, 3)
|
||||
|
||||
return Time.zone.at(value.to_i) if value.is_a?(Numeric)
|
||||
|
||||
### GPSLogger for Android case ###
|
||||
time = feature.dig(:properties, :time)
|
||||
|
||||
Time.zone.parse(time).to_i if time.present?
|
||||
### /GPSLogger for Android case ###
|
||||
end
|
||||
|
||||
def speed(feature)
|
||||
feature.dig(:properties, :speed).to_f.round(1)
|
||||
end
|
||||
|
||||
def accuracy(feature)
|
||||
feature.dig(:properties, :accuracy) || feature.dig(:properties, :horizontal_accuracy)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class Gpx::TrackParser
|
|||
altitude: point['ele'].to_i,
|
||||
timestamp: Time.parse(point['time']).to_i,
|
||||
import_id: import.id,
|
||||
velocity: speed(point),
|
||||
raw_data: point,
|
||||
user_id:
|
||||
)
|
||||
|
|
@ -54,4 +55,12 @@ class Gpx::TrackParser
|
|||
user_id:
|
||||
)
|
||||
end
|
||||
|
||||
def speed(point)
|
||||
return if point['extensions'].blank?
|
||||
|
||||
(
|
||||
point.dig('extensions', 'speed') || point.dig('extensions', 'TrackPointExtension', 'speed')
|
||||
).to_f.round(1)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ area_visits_calculation_scheduling_job:
|
|||
class: "AreaVisitsCalculationSchedulingJob"
|
||||
queue: visit_suggesting
|
||||
|
||||
visit_suggesting_job:
|
||||
cron: "0 1 * * *" # every day at 1:00
|
||||
class: "VisitSuggestingJob"
|
||||
queue: visit_suggesting
|
||||
# Disabled until fixed
|
||||
# visit_suggesting_job:
|
||||
# cron: "0 1 * * *" # every day at 1:00
|
||||
# class: "VisitSuggestingJob"
|
||||
# queue: visit_suggesting
|
||||
|
||||
watcher_job:
|
||||
cron: "0 */1 * * *" # every 1 hour
|
||||
|
|
|
|||
23
spec/fixtures/files/geojson/gpslogger_example.json
vendored
Normal file
23
spec/fixtures/files/geojson/gpslogger_example.json
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"features": [
|
||||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
106.64234449272531,
|
||||
10.758321212464024
|
||||
],
|
||||
"type": "Point"
|
||||
},
|
||||
"properties": {
|
||||
"accuracy": 4.7551565,
|
||||
"altitude": 17.634344400269068,
|
||||
"provider": "gps",
|
||||
"speed": 1.2,
|
||||
"time": "2024-11-03T16:30:11.331+07:00",
|
||||
"time_long": 1730626211331
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
],
|
||||
"type": "FeatureCollection"
|
||||
}
|
||||
31
spec/fixtures/files/gpx/garmin_example.gpx
vendored
Normal file
31
spec/fixtures/files/gpx/garmin_example.gpx
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.1" creator="GPSLogger 131 - http://gpslogger.mendhak.com/"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1"
|
||||
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2"
|
||||
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd
|
||||
http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd
|
||||
">
|
||||
<metadata>
|
||||
<time>2024-11-03T16:30:11.331+07:00</time>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>20241103</name>
|
||||
<trkseg>
|
||||
<trkpt lat="10.758321212464024" lon="106.64234449272531">
|
||||
<ele>17.634344400269068</ele>
|
||||
<time>2024-11-03T16:30:11.331+07:00</time>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
<gpxtpx:speed>2.8</gpxtpx:speed>
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
<geoidheight>-1.6</geoidheight>
|
||||
<src>gps</src>
|
||||
<sat>3</sat>
|
||||
<hdop>1.9</hdop>
|
||||
<vdop>8.6</vdop>
|
||||
<pdop>8.8</pdop>
|
||||
</trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
108
spec/services/geojson/params_spec.rb
Normal file
108
spec/services/geojson/params_spec.rb
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Geojson::Params do
|
||||
describe '#call' do
|
||||
let(:file_path) { Rails.root.join('spec/fixtures/files/geojson/export.json') }
|
||||
let(:file) { File.read(file_path) }
|
||||
let(:json) { JSON.parse(file) }
|
||||
let(:params) { described_class.new(json) }
|
||||
|
||||
subject { params.call }
|
||||
|
||||
it 'returns an array of points' do
|
||||
expect(subject).to be_an_instance_of(Array)
|
||||
expect(subject.first).to be_an_instance_of(Hash)
|
||||
end
|
||||
|
||||
it 'returns the correct data for each point' do
|
||||
expect(subject.first).to eq(
|
||||
latitude: '0.0',
|
||||
longitude: '0.0',
|
||||
battery_status: nil,
|
||||
battery: nil,
|
||||
timestamp: Time.zone.at(1_609_459_201),
|
||||
altitude: 1,
|
||||
velocity: 0,
|
||||
tracker_id: nil,
|
||||
ssid: nil,
|
||||
accuracy: 1,
|
||||
vertical_accuracy: 1,
|
||||
raw_data: {
|
||||
'type' => 'Feature',
|
||||
'geometry' => {
|
||||
'type' => 'Point',
|
||||
'coordinates' => [
|
||||
'0.0',
|
||||
'0.0'
|
||||
]
|
||||
},
|
||||
'properties' => {
|
||||
'battery_status' => 'unplugged',
|
||||
'ping' => 'MyString',
|
||||
'battery' => 1,
|
||||
'tracker_id' => 'MyString',
|
||||
'topic' => 'MyString',
|
||||
'altitude' => 1,
|
||||
'longitude' => '0.1',
|
||||
'velocity' => 'MyString',
|
||||
'trigger' => 'background_event',
|
||||
'bssid' => 'MyString',
|
||||
'ssid' => 'MyString',
|
||||
'connection' => 'wifi',
|
||||
'vertical_accuracy' => 1,
|
||||
'accuracy' => 1,
|
||||
'timestamp' => 1_609_459_201,
|
||||
'latitude' => '0.1',
|
||||
'mode' => 1,
|
||||
'inrids' => [],
|
||||
'in_regions' => [],
|
||||
'raw_data' => '',
|
||||
'city' => nil,
|
||||
'country' => nil,
|
||||
'geodata' => {}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the json is exported from GPSLogger' do
|
||||
let(:file_path) { Rails.root.join('spec/fixtures/files/geojson/gpslogger_example.json') }
|
||||
|
||||
it 'returns the correct data for each point' do
|
||||
expect(subject.first).to eq(
|
||||
latitude: 10.758321212464024,
|
||||
longitude: 106.64234449272531,
|
||||
battery_status: nil,
|
||||
battery: nil,
|
||||
timestamp: Time.parse('2024-11-03T16:30:11.331+07:00').to_i,
|
||||
altitude: 17.634344400269068,
|
||||
velocity: 1.2,
|
||||
tracker_id: nil,
|
||||
ssid: nil,
|
||||
accuracy: 4.7551565,
|
||||
vertical_accuracy: nil,
|
||||
raw_data: {
|
||||
'geometry' => {
|
||||
'coordinates' => [
|
||||
106.64234449272531,
|
||||
10.758321212464024
|
||||
],
|
||||
'type' => 'Point'
|
||||
},
|
||||
'properties' => {
|
||||
'accuracy' => 4.7551565,
|
||||
'altitude' => 17.634344400269068,
|
||||
'provider' => 'gps',
|
||||
'speed' => 1.2,
|
||||
'time' => '2024-11-03T16:30:11.331+07:00',
|
||||
'time_long' => 1_730_626_211_331
|
||||
},
|
||||
'type' => 'Feature'
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -11,7 +11,6 @@ RSpec.describe Gpx::TrackParser do
|
|||
let(:raw_data) { Hash.from_xml(File.read(file_path)) }
|
||||
let(:import) { create(:import, user:, name: 'gpx_track.gpx', raw_data:) }
|
||||
|
||||
context 'when file exists' do
|
||||
context 'when file has a single segment' do
|
||||
it 'creates points' do
|
||||
expect { parser }.to change { Point.count }.by(301)
|
||||
|
|
@ -37,7 +36,6 @@ RSpec.describe Gpx::TrackParser do
|
|||
parser
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when file has multiple tracks' do
|
||||
let(:file_path) { Rails.root.join('spec/fixtures/files/gpx/gpx_track_multiple_tracks.gpx') }
|
||||
|
|
@ -51,6 +49,30 @@ RSpec.describe Gpx::TrackParser do
|
|||
|
||||
parser
|
||||
end
|
||||
|
||||
it 'creates points with correct data' do
|
||||
parser
|
||||
|
||||
expect(Point.first.latitude).to eq(37.17221.to_d)
|
||||
expect(Point.first.longitude).to eq(-3.55468.to_d)
|
||||
expect(Point.first.altitude).to eq(1066)
|
||||
expect(Point.first.timestamp).to eq(Time.zone.parse('2024-04-21T10:19:55Z').to_i)
|
||||
expect(Point.first.velocity).to eq('2.9')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when file exported from Garmin' do
|
||||
let(:file_path) { Rails.root.join('spec/fixtures/files/gpx/garmin_example.gpx') }
|
||||
|
||||
it 'creates points with correct data' do
|
||||
parser
|
||||
|
||||
expect(Point.first.latitude).to eq(10.758321.to_d)
|
||||
expect(Point.first.longitude).to eq(106.642344.to_d)
|
||||
expect(Point.first.altitude).to eq(17)
|
||||
expect(Point.first.timestamp).to eq(1_730_626_211)
|
||||
expect(Point.first.velocity).to eq('2.8')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue