diff --git a/app/jobs/import_job.rb b/app/jobs/import_job.rb index f421b927..5a13d76d 100644 --- a/app/jobs/import_job.rb +++ b/app/jobs/import_job.rb @@ -32,6 +32,7 @@ class ImportJob < ApplicationJob when 'owntracks' then OwnTracks::ExportParser when 'gpx' then Gpx::TrackParser when 'immich_api' then Immich::ImportParser + when 'geojson' then Geojson::ImportParser end end diff --git a/app/models/import.rb b/app/models/import.rb index 332eec18..133f1783 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -10,6 +10,6 @@ class Import < ApplicationRecord enum source: { google_semantic_history: 0, owntracks: 1, google_records: 2, - google_phone_takeout: 3, gpx: 4, immich_api: 5 + google_phone_takeout: 3, gpx: 4, immich_api: 5, geojson: 6 } end diff --git a/app/services/geojson/import_parser.rb b/app/services/geojson/import_parser.rb new file mode 100644 index 00000000..ba3d333f --- /dev/null +++ b/app/services/geojson/import_parser.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class Geojson::ImportParser + attr_reader :import, :json, :user_id + + def initialize(import, user_id) + @import = import + @json = import.raw_data + @user_id = user_id + end + + def call + data = Geojson::Params.new(json).call + + data.each do |point| + next if point_exists?(point, user_id) + + Point.create!(point.merge(user_id:, import_id: import.id)) + end + end + + private + + def point_exists?(params, user_id) + Point.exists?( + latitude: params[:latitude], + longitude: params[:longitude], + timestamp: params[:timestamp], + user_id: + ) + end +end diff --git a/app/services/geojson/params.rb b/app/services/geojson/params.rb new file mode 100644 index 00000000..c87ad072 --- /dev/null +++ b/app/services/geojson/params.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +class Geojson::Params + attr_reader :json + + def initialize(json) + @json = json.with_indifferent_access + end + + def call + json['features'].map do |point| + next if point[:geometry].nil? || point.dig(:properties, :timestamp).nil? + + { + latitude: point[:geometry][:coordinates][1], + longitude: point[:geometry][:coordinates][0], + battery_status: point[:properties][:battery_state], + battery: battery_level(point[:properties][:battery_level]), + timestamp: Time.zone.at(point[:properties][:timestamp]), + altitude: point[:properties][:altitude], + velocity: point[:properties][:speed], + tracker_id: point[:properties][:device_id], + ssid: point[:properties][:wifi], + accuracy: point[:properties][:horizontal_accuracy], + vertical_accuracy: point[:properties][:vertical_accuracy], + raw_data: point + } + end.compact + end + + private + + def battery_level(level) + value = (level.to_f * 100).to_i + + value.positive? ? value : nil + end +end diff --git a/app/views/imports/_form.html.erb b/app/views/imports/_form.html.erb index e5684a7f..83797c82 100644 --- a/app/views/imports/_form.html.erb +++ b/app/views/imports/_form.html.erb @@ -22,6 +22,15 @@

A JSON file you exported by pressing Download button in top right corner of OwnTracks web interface

+
+
+ +

A valid GeoJSON file. For example, a file, exported from a Dawarich instance

+
+