mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 01:31:39 -05:00
Add device support to geodata importers
This commit is contained in:
parent
a96517caf1
commit
a5e07def23
9 changed files with 44 additions and 53 deletions
|
|
@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
- Internal data structure for separate devices in a single user account.
|
- Internal data structure for separate devices in a single user account.
|
||||||
- [ ] Immich and Photoprism integrations should fill all possible fields in points table
|
- [ ] Immich and Photoprism integrations should fill all possible fields in points table
|
||||||
|
- Geodata from Immich and Photoprism now will also write `tracker_id` to the points table. This will allow to group points by device. It's a good idea to delete your existing imports from Photoprism and Immich and import them again. This will remove existing points and re-import them as long as photos are still available.
|
||||||
|
- [ ] Add tracker_id index to points table
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ module PointValidation
|
||||||
Point.where(
|
Point.where(
|
||||||
lonlat: params[:lonlat],
|
lonlat: params[:lonlat],
|
||||||
timestamp: params[:timestamp].to_i,
|
timestamp: params[:timestamp].to_i,
|
||||||
|
tracker_id: params[:tracker_id],
|
||||||
user_id:
|
user_id:
|
||||||
).exists?
|
).exists?
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ class Immich::ImportGeodata
|
||||||
latitude: asset['exifInfo']['latitude'],
|
latitude: asset['exifInfo']['latitude'],
|
||||||
longitude: asset['exifInfo']['longitude'],
|
longitude: asset['exifInfo']['longitude'],
|
||||||
lonlat: "SRID=4326;POINT(#{asset['exifInfo']['longitude']} #{asset['exifInfo']['latitude']})",
|
lonlat: "SRID=4326;POINT(#{asset['exifInfo']['longitude']} #{asset['exifInfo']['latitude']})",
|
||||||
timestamp: Time.zone.parse(asset['exifInfo']['dateTimeOriginal']).to_i
|
timestamp: Time.zone.parse(asset['exifInfo']['dateTimeOriginal']).to_i,
|
||||||
|
tracker_id: asset['deviceId']
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,8 @@ class Photoprism::ImportGeodata
|
||||||
latitude: asset['Lat'],
|
latitude: asset['Lat'],
|
||||||
longitude: asset['Lng'],
|
longitude: asset['Lng'],
|
||||||
lonlat: "SRID=4326;POINT(#{asset['Lng']} #{asset['Lat']})",
|
lonlat: "SRID=4326;POINT(#{asset['Lng']} #{asset['Lat']})",
|
||||||
timestamp: Time.zone.parse(asset['TakenAt']).to_i
|
timestamp: Time.zone.parse(asset['TakenAt']).to_i,
|
||||||
|
tracker_id: "#{asset['CameraMake']} #{asset['CameraModel']}"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class Photos::Importer
|
||||||
|
|
||||||
def create_point(point, index)
|
def create_point(point, index)
|
||||||
return 0 unless valid?(point)
|
return 0 unless valid?(point)
|
||||||
return 0 if point_exists?(point, point['timestamp'])
|
return 0 if point_exists?(point, user_id)
|
||||||
|
|
||||||
Point.create(
|
Point.create(
|
||||||
lonlat: point['lonlat'],
|
lonlat: point['lonlat'],
|
||||||
|
|
@ -28,6 +28,7 @@ class Photos::Importer
|
||||||
timestamp: point['timestamp'].to_i,
|
timestamp: point['timestamp'].to_i,
|
||||||
raw_data: point,
|
raw_data: point,
|
||||||
import_id: import.id,
|
import_id: import.id,
|
||||||
|
tracker_id: point['tracker_id'],
|
||||||
user_id:
|
user_id:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
2
spec/fixtures/files/immich/response.json
vendored
2
spec/fixtures/files/immich/response.json
vendored
|
|
@ -3,6 +3,7 @@
|
||||||
{
|
{
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
|
"deviceId": "MyString",
|
||||||
"exifInfo": {
|
"exifInfo": {
|
||||||
"dateTimeOriginal": "2022-12-31T23:17:06.170Z",
|
"dateTimeOriginal": "2022-12-31T23:17:06.170Z",
|
||||||
"latitude": 52.0000,
|
"latitude": 52.0000,
|
||||||
|
|
@ -10,6 +11,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"deviceId": "MyString",
|
||||||
"exifInfo": {
|
"exifInfo": {
|
||||||
"dateTimeOriginal": "2022-12-31T23:21:53.140Z",
|
"dateTimeOriginal": "2022-12-31T23:21:53.140Z",
|
||||||
"latitude": 52.0000,
|
"latitude": 52.0000,
|
||||||
|
|
|
||||||
|
|
@ -104,56 +104,13 @@ RSpec.describe PointValidation do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with integration tests', :db do
|
context 'with point existing in device scope' do
|
||||||
# These tests require a database with PostGIS support
|
let(:existing_point) do
|
||||||
# Only run them if using real database integration
|
create(:point, lonlat: 'POINT(10.5 50.5)', timestamp: Time.now.to_i, tracker_id: '123', user_id: user.id)
|
||||||
|
|
||||||
let(:existing_timestamp) { 1_650_000_000 }
|
|
||||||
let(:existing_point_params) do
|
|
||||||
{
|
|
||||||
lonlat: 'POINT(10.5 50.5)',
|
|
||||||
timestamp: existing_timestamp,
|
|
||||||
user_id: user.id
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
it 'returns true' do
|
||||||
# Skip this context if not in integration mode
|
expect(validator.point_exists?(existing_point, user.id)).to be true
|
||||||
skip 'Skipping integration tests' unless ENV['RUN_INTEGRATION_TESTS']
|
|
||||||
|
|
||||||
# Create a point in the database
|
|
||||||
existing_point = Point.create!(
|
|
||||||
lonlat: "POINT(#{existing_point_params[:longitude]} #{existing_point_params[:latitude]})",
|
|
||||||
timestamp: existing_timestamp,
|
|
||||||
user_id: user.id
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true when a point with same coordinates and timestamp exists' do
|
|
||||||
params = {
|
|
||||||
lonlat: 'POINT(10.5 50.5)',
|
|
||||||
timestamp: existing_timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(validator.point_exists?(params, user.id)).to be true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false when a point with different coordinates exists' do
|
|
||||||
params = {
|
|
||||||
lonlat: 'POINT(10.6 50.5)',
|
|
||||||
timestamp: existing_timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(validator.point_exists?(params, user.id)).to be false
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false when a point with different timestamp exists' do
|
|
||||||
params = {
|
|
||||||
lonlat: 'POINT(10.5 50.5)',
|
|
||||||
timestamp: existing_timestamp + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(validator.point_exists?(params, user.id)).to be false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,22 @@ require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe 'Api::V1::Countries::Borders', type: :request do
|
RSpec.describe 'Api::V1::Countries::Borders', type: :request do
|
||||||
describe 'GET /index' do
|
describe 'GET /index' do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
it 'returns a list of countries with borders' do
|
it 'returns a list of countries with borders' do
|
||||||
get '/api/v1/countries/borders'
|
get '/api/v1/countries/borders', headers: { 'Authorization' => "Bearer #{user.api_key}" }
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(response.body).to include('AF')
|
expect(response.body).to include('AF')
|
||||||
expect(response.body).to include('ZW')
|
expect(response.body).to include('ZW')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when user is not authenticated' do
|
||||||
|
it 'returns http unauthorized' do
|
||||||
|
get '/api/v1/countries/borders'
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,28 @@ RSpec.describe Photos::Importer do
|
||||||
|
|
||||||
context 'when there are points with the same coordinates' do
|
context 'when there are points with the same coordinates' do
|
||||||
let!(:existing_point) do
|
let!(:existing_point) do
|
||||||
create(:point, lonlat: 'POINT(30.0000 59.0000)', timestamp: 978_296_400, user:, device:)
|
create(:point,
|
||||||
|
lonlat: 'SRID=4326;POINT(30.0000 59.0000)',
|
||||||
|
timestamp: 978_296_400,
|
||||||
|
user: user,
|
||||||
|
device: device,
|
||||||
|
tracker_id: nil
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates only new points' do
|
it 'creates only new points' do
|
||||||
expect { service }.to change { Point.count }.by(1)
|
expect { service }.to change { Point.count }.by(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not create duplicate points' do
|
||||||
|
service
|
||||||
|
points = Point.where(
|
||||||
|
lonlat: 'SRID=4326;POINT(30.0000 59.0000)',
|
||||||
|
timestamp: 978_296_400,
|
||||||
|
user_id: user.id
|
||||||
|
)
|
||||||
|
expect(points.count).to eq(1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue