Skip to content

Commit 657f69d

Browse files
authored
Merge pull request #374 from Freika/fix/gpx-geojson-speed-recording
Fix/gpx geojson speed recording
2 parents fb799eb + 3880d51 commit 657f69d

File tree

9 files changed

+251
-30
lines changed

9 files changed

+251
-30
lines changed

.app_version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.16.0
1+
0.16.1

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8+
# 0.16.1 - 2024-11-08
9+
10+
### Fixed
11+
12+
- Speed is now being recorded into points when a GPX file is being imported. Previously, the speed was not being recorded.
13+
- GeoJSON file from GPSLogger now can be imported to Dawarich. Previously, the import was failing due to incorrect parsing of the file.
14+
15+
### Changed
16+
17+
- The Vists suggestion job is disabled. It will be re-enabled in the future with a new approach to the visit suggestion process.
18+
819
# 0.16.0 - 2024-11-07
920

1021
## The Websockets release

app/services/geojson/params.rb

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,30 @@ def build_point(feature)
3939
battery: battery_level(feature[:properties][:battery_level]),
4040
timestamp: timestamp(feature),
4141
altitude: altitude(feature),
42-
velocity: feature[:properties][:speed],
42+
velocity: speed(feature),
4343
tracker_id: feature[:properties][:device_id],
4444
ssid: feature[:properties][:wifi],
45-
accuracy: feature[:properties][:horizontal_accuracy],
45+
accuracy: accuracy(feature),
4646
vertical_accuracy: feature[:properties][:vertical_accuracy],
4747
raw_data: feature
4848
}
4949
end
5050

5151
def build_line(feature)
5252
feature[:geometry][:coordinates].map do |point|
53-
build_line_point(feature, point)
53+
build_line_point(point)
5454
end
5555
end
5656

5757
def build_multi_line(feature)
5858
feature[:geometry][:coordinates].map do |line|
5959
line.map do |point|
60-
build_line_point(feature, point)
60+
build_line_point(point)
6161
end
6262
end
6363
end
6464

65-
def build_line_point(feature, point)
65+
def build_line_point(point)
6666
{
6767
latitude: point[1],
6868
longitude: point[0],
@@ -84,7 +84,23 @@ def altitude(feature)
8484
def timestamp(feature)
8585
return Time.zone.at(feature[3]) if feature.is_a?(Array)
8686

87-
value = feature.dig(:properties, :timestamp) || feature.dig(:geometry, :coordinates, 3)
88-
Time.zone.at(value)
87+
value = feature.dig(:properties, :timestamp) ||
88+
feature.dig(:geometry, :coordinates, 3)
89+
90+
return Time.zone.at(value.to_i) if value.is_a?(Numeric)
91+
92+
### GPSLogger for Android case ###
93+
time = feature.dig(:properties, :time)
94+
95+
Time.zone.parse(time).to_i if time.present?
96+
### /GPSLogger for Android case ###
97+
end
98+
99+
def speed(feature)
100+
feature.dig(:properties, :speed).to_f.round(1)
101+
end
102+
103+
def accuracy(feature)
104+
feature.dig(:properties, :accuracy) || feature.dig(:properties, :horizontal_accuracy)
89105
end
90106
end

app/services/gpx/track_parser.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def create_point(point, index)
3939
altitude: point['ele'].to_i,
4040
timestamp: Time.parse(point['time']).to_i,
4141
import_id: import.id,
42+
velocity: speed(point),
4243
raw_data: point,
4344
user_id:
4445
)
@@ -54,4 +55,12 @@ def point_exists?(point)
5455
user_id:
5556
)
5657
end
58+
59+
def speed(point)
60+
return if point['extensions'].blank?
61+
62+
(
63+
point.dig('extensions', 'speed') || point.dig('extensions', 'TrackPointExtension', 'speed')
64+
).to_f.round(1)
65+
end
5766
end

config/schedule.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ area_visits_calculation_scheduling_job:
1010
class: "AreaVisitsCalculationSchedulingJob"
1111
queue: visit_suggesting
1212

13-
visit_suggesting_job:
14-
cron: "0 1 * * *" # every day at 1:00
15-
class: "VisitSuggestingJob"
16-
queue: visit_suggesting
13+
# Disabled until fixed
14+
# visit_suggesting_job:
15+
# cron: "0 1 * * *" # every day at 1:00
16+
# class: "VisitSuggestingJob"
17+
# queue: visit_suggesting
1718

1819
watcher_job:
1920
cron: "0 */1 * * *" # every 1 hour
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"features": [
3+
{
4+
"geometry": {
5+
"coordinates": [
6+
106.64234449272531,
7+
10.758321212464024
8+
],
9+
"type": "Point"
10+
},
11+
"properties": {
12+
"accuracy": 4.7551565,
13+
"altitude": 17.634344400269068,
14+
"provider": "gps",
15+
"speed": 1.2,
16+
"time": "2024-11-03T16:30:11.331+07:00",
17+
"time_long": 1730626211331
18+
},
19+
"type": "Feature"
20+
}
21+
],
22+
"type": "FeatureCollection"
23+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<gpx version="1.1" creator="GPSLogger 131 - http://gpslogger.mendhak.com/"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1"
4+
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2"
5+
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd
6+
http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd
7+
">
8+
<metadata>
9+
<time>2024-11-03T16:30:11.331+07:00</time>
10+
</metadata>
11+
<trk>
12+
<name>20241103</name>
13+
<trkseg>
14+
<trkpt lat="10.758321212464024" lon="106.64234449272531">
15+
<ele>17.634344400269068</ele>
16+
<time>2024-11-03T16:30:11.331+07:00</time>
17+
<extensions>
18+
<gpxtpx:TrackPointExtension>
19+
<gpxtpx:speed>2.8</gpxtpx:speed>
20+
</gpxtpx:TrackPointExtension>
21+
</extensions>
22+
<geoidheight>-1.6</geoidheight>
23+
<src>gps</src>
24+
<sat>3</sat>
25+
<hdop>1.9</hdop>
26+
<vdop>8.6</vdop>
27+
<pdop>8.8</pdop>
28+
</trkpt>
29+
</trkseg>
30+
</trk>
31+
</gpx>

spec/services/geojson/params_spec.rb

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.describe Geojson::Params do
6+
describe '#call' do
7+
let(:file_path) { Rails.root.join('spec/fixtures/files/geojson/export.json') }
8+
let(:file) { File.read(file_path) }
9+
let(:json) { JSON.parse(file) }
10+
let(:params) { described_class.new(json) }
11+
12+
subject { params.call }
13+
14+
it 'returns an array of points' do
15+
expect(subject).to be_an_instance_of(Array)
16+
expect(subject.first).to be_an_instance_of(Hash)
17+
end
18+
19+
it 'returns the correct data for each point' do
20+
expect(subject.first).to eq(
21+
latitude: '0.0',
22+
longitude: '0.0',
23+
battery_status: nil,
24+
battery: nil,
25+
timestamp: Time.zone.at(1_609_459_201),
26+
altitude: 1,
27+
velocity: 0,
28+
tracker_id: nil,
29+
ssid: nil,
30+
accuracy: 1,
31+
vertical_accuracy: 1,
32+
raw_data: {
33+
'type' => 'Feature',
34+
'geometry' => {
35+
'type' => 'Point',
36+
'coordinates' => [
37+
'0.0',
38+
'0.0'
39+
]
40+
},
41+
'properties' => {
42+
'battery_status' => 'unplugged',
43+
'ping' => 'MyString',
44+
'battery' => 1,
45+
'tracker_id' => 'MyString',
46+
'topic' => 'MyString',
47+
'altitude' => 1,
48+
'longitude' => '0.1',
49+
'velocity' => 'MyString',
50+
'trigger' => 'background_event',
51+
'bssid' => 'MyString',
52+
'ssid' => 'MyString',
53+
'connection' => 'wifi',
54+
'vertical_accuracy' => 1,
55+
'accuracy' => 1,
56+
'timestamp' => 1_609_459_201,
57+
'latitude' => '0.1',
58+
'mode' => 1,
59+
'inrids' => [],
60+
'in_regions' => [],
61+
'raw_data' => '',
62+
'city' => nil,
63+
'country' => nil,
64+
'geodata' => {}
65+
}
66+
}
67+
)
68+
end
69+
70+
context 'when the json is exported from GPSLogger' do
71+
let(:file_path) { Rails.root.join('spec/fixtures/files/geojson/gpslogger_example.json') }
72+
73+
it 'returns the correct data for each point' do
74+
expect(subject.first).to eq(
75+
latitude: 10.758321212464024,
76+
longitude: 106.64234449272531,
77+
battery_status: nil,
78+
battery: nil,
79+
timestamp: Time.parse('2024-11-03T16:30:11.331+07:00').to_i,
80+
altitude: 17.634344400269068,
81+
velocity: 1.2,
82+
tracker_id: nil,
83+
ssid: nil,
84+
accuracy: 4.7551565,
85+
vertical_accuracy: nil,
86+
raw_data: {
87+
'geometry' => {
88+
'coordinates' => [
89+
106.64234449272531,
90+
10.758321212464024
91+
],
92+
'type' => 'Point'
93+
},
94+
'properties' => {
95+
'accuracy' => 4.7551565,
96+
'altitude' => 17.634344400269068,
97+
'provider' => 'gps',
98+
'speed' => 1.2,
99+
'time' => '2024-11-03T16:30:11.331+07:00',
100+
'time_long' => 1_730_626_211_331
101+
},
102+
'type' => 'Feature'
103+
}
104+
)
105+
end
106+
end
107+
end
108+
end

spec/services/gpx/track_parser_spec.rb

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,29 @@
1111
let(:raw_data) { Hash.from_xml(File.read(file_path)) }
1212
let(:import) { create(:import, user:, name: 'gpx_track.gpx', raw_data:) }
1313

14-
context 'when file exists' do
15-
context 'when file has a single segment' do
16-
it 'creates points' do
17-
expect { parser }.to change { Point.count }.by(301)
18-
end
14+
context 'when file has a single segment' do
15+
it 'creates points' do
16+
expect { parser }.to change { Point.count }.by(301)
17+
end
1918

20-
it 'broadcasts importing progress' do
21-
expect_any_instance_of(Imports::Broadcaster).to receive(:broadcast_import_progress).exactly(301).times
19+
it 'broadcasts importing progress' do
20+
expect_any_instance_of(Imports::Broadcaster).to receive(:broadcast_import_progress).exactly(301).times
2221

23-
parser
24-
end
22+
parser
2523
end
24+
end
2625

27-
context 'when file has multiple segments' do
28-
let(:file_path) { Rails.root.join('spec/fixtures/files/gpx/gpx_track_multiple_segments.gpx') }
26+
context 'when file has multiple segments' do
27+
let(:file_path) { Rails.root.join('spec/fixtures/files/gpx/gpx_track_multiple_segments.gpx') }
2928

30-
it 'creates points' do
31-
expect { parser }.to change { Point.count }.by(558)
32-
end
29+
it 'creates points' do
30+
expect { parser }.to change { Point.count }.by(558)
31+
end
3332

34-
it 'broadcasts importing progress' do
35-
expect_any_instance_of(Imports::Broadcaster).to receive(:broadcast_import_progress).exactly(558).times
33+
it 'broadcasts importing progress' do
34+
expect_any_instance_of(Imports::Broadcaster).to receive(:broadcast_import_progress).exactly(558).times
3635

37-
parser
38-
end
36+
parser
3937
end
4038
end
4139

@@ -51,6 +49,30 @@
5149

5250
parser
5351
end
52+
53+
it 'creates points with correct data' do
54+
parser
55+
56+
expect(Point.first.latitude).to eq(37.17221.to_d)
57+
expect(Point.first.longitude).to eq(-3.55468.to_d)
58+
expect(Point.first.altitude).to eq(1066)
59+
expect(Point.first.timestamp).to eq(Time.zone.parse('2024-04-21T10:19:55Z').to_i)
60+
expect(Point.first.velocity).to eq('2.9')
61+
end
62+
end
63+
64+
context 'when file exported from Garmin' do
65+
let(:file_path) { Rails.root.join('spec/fixtures/files/gpx/garmin_example.gpx') }
66+
67+
it 'creates points with correct data' do
68+
parser
69+
70+
expect(Point.first.latitude).to eq(10.758321.to_d)
71+
expect(Point.first.longitude).to eq(106.642344.to_d)
72+
expect(Point.first.altitude).to eq(17)
73+
expect(Point.first.timestamp).to eq(1_730_626_211)
74+
expect(Point.first.velocity).to eq('2.8')
75+
end
5476
end
5577
end
5678
end

0 commit comments

Comments
 (0)