mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
Add docs and few fixes
This commit is contained in:
parent
073b3afc71
commit
fea87b85bb
17 changed files with 2729 additions and 149 deletions
2087
CHANGELOG.md
2087
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
|
@ -107,3 +107,8 @@
|
|||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.clickable-area,
|
||||
.leaflet-interactive {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ import {
|
|||
getSpeedColor
|
||||
} from "../maps/polylines";
|
||||
|
||||
import { fetchAndDrawAreas } from "../maps/areas";
|
||||
import { handleAreaCreated } from "../maps/areas";
|
||||
import { fetchAndDrawAreas, handleAreaCreated } from "../maps/areas";
|
||||
|
||||
import { showFlashMessage, fetchAndDisplayPhotos, debounce } from "../maps/helpers";
|
||||
|
||||
|
|
@ -67,7 +66,7 @@ export default class extends Controller {
|
|||
imperial: this.distanceUnit === 'mi',
|
||||
metric: this.distanceUnit === 'km',
|
||||
maxWidth: 120
|
||||
}).addTo(this.map)
|
||||
}).addTo(this.map);
|
||||
|
||||
// Add stats control
|
||||
const StatsControl = L.Control.extend({
|
||||
|
|
@ -107,7 +106,8 @@ export default class extends Controller {
|
|||
// Create a proper Leaflet layer for fog
|
||||
this.fogOverlay = createFogOverlay();
|
||||
|
||||
this.areasLayer = L.layerGroup(); // Initialize areas layer
|
||||
this.areasLayer = L.layerGroup(); // Initialize areasLayer
|
||||
|
||||
this.photoMarkers = L.layerGroup();
|
||||
|
||||
this.setupScratchLayer(this.countryCodesMap);
|
||||
|
|
@ -123,7 +123,7 @@ export default class extends Controller {
|
|||
Heatmap: this.heatmapLayer,
|
||||
"Fog of War": new this.fogOverlay(),
|
||||
"Scratch map": this.scratchLayer,
|
||||
Areas: this.areasLayer,
|
||||
Areas: this.areasLayer, // Add areasLayer to the control
|
||||
Photos: this.photoMarkers
|
||||
};
|
||||
|
||||
|
|
@ -166,6 +166,20 @@ export default class extends Controller {
|
|||
// Fetch and draw areas when the map is loaded
|
||||
fetchAndDrawAreas(this.areasLayer, this.apiKey);
|
||||
|
||||
// Add a simple test circle to the map
|
||||
const testCircle = L.circle([52.514568, 13.350111], {
|
||||
radius: 100,
|
||||
color: 'blue',
|
||||
fillColor: '#30f',
|
||||
fillOpacity: 0.5,
|
||||
interactive: true,
|
||||
zIndexOffset: 1000
|
||||
}).addTo(this.map);
|
||||
|
||||
testCircle.on('mouseover', () => {
|
||||
console.log('Mouse over test circle');
|
||||
});
|
||||
|
||||
let fogEnabled = false;
|
||||
|
||||
// Hide fog by default
|
||||
|
|
@ -248,10 +262,13 @@ export default class extends Controller {
|
|||
}
|
||||
// Store panel state before disconnecting
|
||||
if (this.rightPanel) {
|
||||
const finalState = document.querySelector('.leaflet-right-panel').style.display !== 'none' ? 'true' : 'false';
|
||||
const panel = document.querySelector('.leaflet-right-panel');
|
||||
const finalState = panel ? (panel.style.display !== 'none' ? 'true' : 'false') : 'false';
|
||||
localStorage.setItem('mapPanelOpen', finalState);
|
||||
}
|
||||
this.map.remove();
|
||||
if (this.map) {
|
||||
this.map.remove();
|
||||
}
|
||||
}
|
||||
|
||||
setupSubscription() {
|
||||
|
|
@ -567,17 +584,26 @@ export default class extends Controller {
|
|||
},
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
featureGroup: this.drawnItems
|
||||
}
|
||||
});
|
||||
|
||||
// Handle circle creation
|
||||
this.map.on(L.Draw.Event.CREATED, (event) => {
|
||||
this.map.on('draw:created', (event) => {
|
||||
const layer = event.layer;
|
||||
|
||||
if (event.layerType === 'circle') {
|
||||
handleAreaCreated(this.areasLayer, layer, this.apiKey);
|
||||
console.log("Circle created, opening popup..."); // Add debug log
|
||||
try {
|
||||
// Add the layer to the map first
|
||||
layer.addTo(this.map);
|
||||
handleAreaCreated(this.areasLayer, layer, this.apiKey);
|
||||
} catch (error) {
|
||||
console.error("Error in handleAreaCreated:", error);
|
||||
console.error(error.stack); // Add stack trace
|
||||
}
|
||||
}
|
||||
|
||||
this.drawnItems.addLayer(layer);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,54 +1,105 @@
|
|||
export function handleAreaCreated(areasLayer, layer, apiKey) {
|
||||
console.log('handleAreaCreated called with apiKey:', apiKey);
|
||||
const radius = layer.getRadius();
|
||||
const center = layer.getLatLng();
|
||||
|
||||
const formHtml = `
|
||||
<div class="card w-96 max-w-sm bg-content-100 shadow-xl">
|
||||
<div class="card w-96 bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">New Area</h2>
|
||||
<form id="circle-form">
|
||||
<form id="circle-form" class="space-y-4">
|
||||
<div class="form-control">
|
||||
<label for="circle-name" class="label">
|
||||
<span class="label-text">Name</span>
|
||||
<span class="label-text">Area Name</span>
|
||||
</label>
|
||||
<input type="text" id="circle-name" name="area[name]" class="input input-bordered input-ghost focus:input-ghost w-full max-w-xs" required>
|
||||
<input type="text"
|
||||
id="circle-name"
|
||||
name="area[name]"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Enter area name"
|
||||
autofocus
|
||||
required>
|
||||
</div>
|
||||
<input type="hidden" name="area[latitude]" value="${center.lat}">
|
||||
<input type="hidden" name="area[longitude]" value="${center.lng}">
|
||||
<input type="hidden" name="area[radius]" value="${radius}">
|
||||
<div class="card-actions justify-end mt-4">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<div class="flex justify-between mt-4">
|
||||
<button type="button"
|
||||
class="btn btn-ghost"
|
||||
onclick="this.closest('.leaflet-popup').querySelector('.leaflet-popup-close-button').click()">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="button" id="save-area-btn" class="btn btn-primary">Save Area</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
layer.bindPopup(
|
||||
formHtml, {
|
||||
maxWidth: "auto",
|
||||
minWidth: 300
|
||||
}
|
||||
).openPopup();
|
||||
console.log('Binding popup to layer');
|
||||
layer.bindPopup(formHtml, {
|
||||
maxWidth: "auto",
|
||||
minWidth: 300,
|
||||
closeButton: true,
|
||||
closeOnClick: false,
|
||||
className: 'area-form-popup'
|
||||
}).openPopup();
|
||||
|
||||
layer.on('popupopen', () => {
|
||||
const form = document.getElementById('circle-form');
|
||||
|
||||
if (!form) return;
|
||||
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
saveArea(new FormData(form), areasLayer, layer, apiKey);
|
||||
});
|
||||
});
|
||||
|
||||
// Add the layer to the areas layer group
|
||||
console.log('Adding layer to areasLayer');
|
||||
areasLayer.addLayer(layer);
|
||||
|
||||
// Bind the event handler immediately after opening the popup
|
||||
setTimeout(() => {
|
||||
console.log('Setting up form handlers');
|
||||
const form = document.getElementById('circle-form');
|
||||
const saveButton = document.getElementById('save-area-btn');
|
||||
const nameInput = document.getElementById('circle-name');
|
||||
|
||||
console.log('Form:', form);
|
||||
console.log('Save button:', saveButton);
|
||||
console.log('Name input:', nameInput);
|
||||
|
||||
if (!form || !saveButton || !nameInput) {
|
||||
console.error('Required elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Focus the name input
|
||||
nameInput.focus();
|
||||
|
||||
// Remove any existing click handlers
|
||||
const newSaveButton = saveButton.cloneNode(true);
|
||||
saveButton.parentNode.replaceChild(newSaveButton, saveButton);
|
||||
|
||||
// Add click handler
|
||||
newSaveButton.addEventListener('click', (e) => {
|
||||
console.log('Save button clicked');
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (!nameInput.value.trim()) {
|
||||
console.log('Name is empty');
|
||||
nameInput.classList.add('input-error');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Creating FormData');
|
||||
const formData = new FormData(form);
|
||||
formData.forEach((value, key) => {
|
||||
console.log(`FormData: ${key} = ${value}`);
|
||||
});
|
||||
|
||||
console.log('Calling saveArea');
|
||||
saveArea(formData, areasLayer, layer, apiKey);
|
||||
});
|
||||
}, 100); // Small delay to ensure DOM is ready
|
||||
}
|
||||
|
||||
export function saveArea(formData, areasLayer, layer, apiKey) {
|
||||
console.log('saveArea called with apiKey:', apiKey);
|
||||
const data = {};
|
||||
formData.forEach((value, key) => {
|
||||
console.log('FormData entry:', key, value);
|
||||
const keys = key.split('[').map(k => k.replace(']', ''));
|
||||
if (keys.length > 1) {
|
||||
if (!data[keys[0]]) data[keys[0]] = {};
|
||||
|
|
@ -58,18 +109,21 @@ export function saveArea(formData, areasLayer, layer, apiKey) {
|
|||
}
|
||||
});
|
||||
|
||||
console.log('Sending fetch request with data:', data);
|
||||
fetch(`/api/v1/areas?api_key=${apiKey}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => {
|
||||
console.log('Received response:', response);
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Area saved successfully:', data);
|
||||
layer.closePopup();
|
||||
layer.bindPopup(`
|
||||
Name: ${data.name}<br>
|
||||
|
|
@ -79,9 +133,13 @@ export function saveArea(formData, areasLayer, layer, apiKey) {
|
|||
|
||||
// Add event listener for the delete button
|
||||
layer.on('popupopen', () => {
|
||||
document.querySelector('.delete-area').addEventListener('click', () => {
|
||||
deleteArea(data.id, areasLayer, layer, apiKey);
|
||||
});
|
||||
const deleteButton = document.querySelector('.delete-area');
|
||||
if (deleteButton) {
|
||||
deleteButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
deleteArea(data.id, areasLayer, layer, apiKey);
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class GoogleMaps::PhoneTakeoutParser
|
|||
end
|
||||
|
||||
def parse_raw_array(raw_data)
|
||||
raw_data.map do |data_point|
|
||||
raw_data.flat_map do |data_point|
|
||||
if data_point.dig('visit', 'topCandidate', 'placeLocation')
|
||||
parse_visit_place_location(data_point)
|
||||
elsif data_point.dig('activity', 'start') && data_point.dig('activity', 'end')
|
||||
|
|
@ -152,7 +152,7 @@ class GoogleMaps::PhoneTakeoutParser
|
|||
elsif data_point['timelinePath']
|
||||
parse_timeline_path(data_point)
|
||||
end
|
||||
end.flatten.compact
|
||||
end.compact
|
||||
end
|
||||
|
||||
def parse_semantic_segments(semantic_segments)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class OwnTracks::Params
|
|||
altitude: params[:alt],
|
||||
accuracy: params[:acc],
|
||||
vertical_accuracy: params[:vac],
|
||||
velocity: params[:vel],
|
||||
velocity: speed,
|
||||
ssid: params[:SSID],
|
||||
bssid: params[:BSSID],
|
||||
tracker_id: params[:tid],
|
||||
|
|
@ -69,4 +69,16 @@ class OwnTracks::Params
|
|||
else 'unknown'
|
||||
end
|
||||
end
|
||||
|
||||
def speed
|
||||
return params[:vel] unless owntracks_point?
|
||||
|
||||
# OwnTracks speed is in km/h, so we need to convert it to m/s
|
||||
# Reference: https://owntracks.org/booklet/tech/json/
|
||||
((params[:vel].to_f * 1000) / 3600).round(1).to_s
|
||||
end
|
||||
|
||||
def owntracks_point?
|
||||
params[:topic].present?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
4
spec/fixtures/files/owntracks/2024-03.rec
vendored
4
spec/fixtures/files/owntracks/2024-03.rec
vendored
|
|
@ -1,5 +1,5 @@
|
|||
2024-03-01T09:03:09Z * {"bs":2,"p":100.266,"batt":94,"_type":"location","tid":"RO","topic":"owntracks/test/iPhone 12 Pro","alt":36,"lon":13.332,"vel":0,"t":"p","BSSID":"b0:f2:8:45:94:33","SSID":"Home Wifi","conn":"w","vac":4,"acc":10,"tst":1709283789,"lat":52.225,"m":1,"inrids":["5f1d1b"],"inregions":["home"],"_http":true}
|
||||
2024-03-01T17:46:02Z * {"bs":1,"p":100.28,"batt":94,"_type":"location","tid":"RO","topic":"owntracks/test/iPhone 12 Pro","alt":36,"lon":13.333,"t":"p","vel":0,"BSSID":"b0:f2:8:45:94:33","conn":"w","SSID":"Home Wifi","vac":3,"cog":98,"acc":9,"tst":1709315162,"lat":52.226,"m":1,"inrids":["5f1d1b"],"inregions":["home"],"_http":true}
|
||||
2024-03-01T09:03:09Z * {"bs":2,"p":100.266,"batt":94,"_type":"location","tid":"RO","topic":"owntracks/test/iPhone 12 Pro","alt":36,"lon":13.332,"vel":5,"t":"p","BSSID":"b0:f2:8:45:94:33","SSID":"Home Wifi","conn":"w","vac":4,"acc":10,"tst":1709283789,"lat":52.225,"m":1,"inrids":["5f1d1b"],"inregions":["home"],"_http":true}
|
||||
2024-03-01T17:46:02Z * {"bs":1,"p":100.28,"batt":94,"_type":"location","tid":"RO","topic":"owntracks/test/iPhone 12 Pro","alt":36,"lon":13.333,"t":"p","vel":5,"BSSID":"b0:f2:8:45:94:33","conn":"w","SSID":"Home Wifi","vac":3,"cog":98,"acc":9,"tst":1709315162,"lat":52.226,"m":1,"inrids":["5f1d1b"],"inregions":["home"],"_http":true}
|
||||
2024-03-01T18:26:55Z * {"lon":13.334,"acc":5,"wtst":1696359532,"event":"leave","rid":"5f1d1b","desc":"home","topic":"owntracks/test/iPhone 12 Pro/event","lat":52.227,"t":"c","tst":1709317615,"tid":"RO","_type":"transition","_http":true}
|
||||
2024-03-01T18:26:55Z * {"cog":40,"batt":85,"lon":13.335,"acc":5,"bs":1,"p":100.279,"vel":3,"vac":3,"lat":52.228,"topic":"owntracks/test/iPhone 12 Pro","t":"c","conn":"m","m":1,"tst":1709317615,"alt":36,"_type":"location","tid":"RO","_http":true}
|
||||
2024-03-01T18:28:30Z * {"cog":38,"batt":85,"lon":13.336,"acc":5,"bs":1,"p":100.349,"vel":3,"vac":3,"lat":52.229,"topic":"owntracks/test/iPhone 12 Pro","t":"v","conn":"m","m":1,"tst":1709317710,"alt":35,"_type":"location","tid":"RO","_http":true}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ RSpec.describe OwnTracks::ExportParser do
|
|||
'altitude' => 36,
|
||||
'accuracy' => 10,
|
||||
'vertical_accuracy' => 4,
|
||||
'velocity' => '0',
|
||||
'velocity' => '1.4',
|
||||
'connection' => 'wifi',
|
||||
'ssid' => 'Home Wifi',
|
||||
'bssid' => 'b0:f2:8:45:94:33',
|
||||
|
|
@ -51,7 +51,7 @@ RSpec.describe OwnTracks::ExportParser do
|
|||
'tid' => 'RO',
|
||||
'tst' => 1_709_283_789,
|
||||
'vac' => 4,
|
||||
'vel' => 0,
|
||||
'vel' => 5,
|
||||
'SSID' => 'Home Wifi',
|
||||
'batt' => 94,
|
||||
'conn' => 'w',
|
||||
|
|
@ -64,6 +64,12 @@ RSpec.describe OwnTracks::ExportParser do
|
|||
}
|
||||
)
|
||||
end
|
||||
|
||||
it 'correctly converts speed' do
|
||||
parser
|
||||
|
||||
expect(Point.first.velocity).to eq('1.4')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ RSpec.describe OwnTracks::Params do
|
|||
altitude: 36,
|
||||
accuracy: 10,
|
||||
vertical_accuracy: 4,
|
||||
velocity: 0,
|
||||
velocity: '1.4',
|
||||
ssid: 'Home Wifi',
|
||||
bssid: 'b0:f2:8:45:94:33',
|
||||
tracker_id: 'RO',
|
||||
|
|
@ -39,7 +39,7 @@ RSpec.describe OwnTracks::Params do
|
|||
'topic' => 'owntracks/test/iPhone 12 Pro',
|
||||
'alt' => 36,
|
||||
'lon' => 13.332,
|
||||
'vel' => 0,
|
||||
'vel' => 5,
|
||||
't' => 'p',
|
||||
'BSSID' => 'b0:f2:8:45:94:33',
|
||||
'SSID' => 'Home Wifi',
|
||||
|
|
|
|||
|
|
@ -16,10 +16,26 @@ describe 'Areas API', type: :request do
|
|||
parameter name: :area, in: :body, schema: {
|
||||
type: :object,
|
||||
properties: {
|
||||
name: { type: :string },
|
||||
latitude: { type: :number },
|
||||
longitude: { type: :number },
|
||||
radius: { type: :number }
|
||||
name: {
|
||||
type: :string,
|
||||
example: 'Home',
|
||||
description: 'The name of the area'
|
||||
},
|
||||
latitude: {
|
||||
type: :number,
|
||||
example: 40.7128,
|
||||
description: 'The latitude of the area'
|
||||
},
|
||||
longitude: {
|
||||
type: :number,
|
||||
example: -74.0060,
|
||||
description: 'The longitude of the area'
|
||||
},
|
||||
radius: {
|
||||
type: :number,
|
||||
example: 100,
|
||||
description: 'The radius of the area in meters'
|
||||
}
|
||||
},
|
||||
required: %w[name latitude longitude radius]
|
||||
}
|
||||
|
|
@ -47,11 +63,31 @@ describe 'Areas API', type: :request do
|
|||
items: {
|
||||
type: :object,
|
||||
properties: {
|
||||
id: { type: :integer },
|
||||
name: { type: :string },
|
||||
latitude: { type: :number },
|
||||
longitude: { type: :number },
|
||||
radius: { type: :number }
|
||||
id: {
|
||||
type: :integer,
|
||||
example: 1,
|
||||
description: 'The ID of the area'
|
||||
},
|
||||
name: {
|
||||
type: :string,
|
||||
example: 'Home',
|
||||
description: 'The name of the area'
|
||||
},
|
||||
latitude: {
|
||||
type: :number,
|
||||
example: 40.7128,
|
||||
description: 'The latitude of the area'
|
||||
},
|
||||
longitude: {
|
||||
type: :number,
|
||||
example: -74.0060,
|
||||
description: 'The longitude of the area'
|
||||
},
|
||||
radius: {
|
||||
type: :number,
|
||||
example: 100,
|
||||
description: 'The radius of the area in meters'
|
||||
}
|
||||
},
|
||||
required: %w[id name latitude longitude radius]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,12 @@ RSpec.describe 'Api::V1::Countries::VisitedCities', type: :request do
|
|||
description 'Returns a list of visited cities and countries based on tracked points within the specified date range'
|
||||
produces 'application/json'
|
||||
|
||||
parameter name: :api_key, in: :query, type: :string, required: true
|
||||
parameter name: :api_key,
|
||||
in: :query,
|
||||
type: :string,
|
||||
required: true,
|
||||
example: 'a1b2c3d4e5f6g7h8i9j0',
|
||||
description: 'Your API authentication key'
|
||||
parameter name: :start_at,
|
||||
in: :query,
|
||||
type: :string,
|
||||
|
|
@ -32,6 +37,36 @@ RSpec.describe 'Api::V1::Countries::VisitedCities', type: :request do
|
|||
data: {
|
||||
type: :array,
|
||||
description: 'Array of countries and their visited cities',
|
||||
example: [
|
||||
{
|
||||
country: 'Germany',
|
||||
cities: [
|
||||
{
|
||||
city: 'Berlin',
|
||||
points: 4394,
|
||||
timestamp: 1_724_868_369,
|
||||
stayed_for: 24_490
|
||||
},
|
||||
{
|
||||
city: 'Munich',
|
||||
points: 2156,
|
||||
timestamp: 1_724_782_369,
|
||||
stayed_for: 12_450
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
country: 'France',
|
||||
cities: [
|
||||
{
|
||||
city: 'Paris',
|
||||
points: 3267,
|
||||
timestamp: 1_724_695_969,
|
||||
stayed_for: 18_720
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
items: {
|
||||
type: :object,
|
||||
properties: {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,22 @@ describe 'Health API', type: :request do
|
|||
tags 'Health'
|
||||
produces 'application/json'
|
||||
response '200', 'Healthy' do
|
||||
schema type: :object,
|
||||
properties: {
|
||||
status: { type: :string }
|
||||
}
|
||||
|
||||
header 'X-Dawarich-Response',
|
||||
type: :string,
|
||||
required: true,
|
||||
example: 'Hey, I\'m alive!',
|
||||
description: "Depending on the authentication status of the request, the response will be different. If the request is authenticated, the response will be 'Hey, I'm alive and authenticated!'. If the request is not authenticated, the response will be 'Hey, I'm alive!'."
|
||||
header 'X-Dawarich-Version',
|
||||
type: :string,
|
||||
required: true,
|
||||
example: '1.0.0',
|
||||
description: 'The version of the application, for example: 1.0.0'
|
||||
|
||||
run_test!
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ describe 'Overland Batches API', type: :request do
|
|||
deferred: 0,
|
||||
significant_change: 'unknown',
|
||||
locations_in_payload: 1,
|
||||
device_id: 'Swagger',
|
||||
device_id: 'iOS device #166',
|
||||
unique_id: '1234567890',
|
||||
wifi: 'unknown',
|
||||
battery_state: 'unknown',
|
||||
battery_level: 0
|
||||
|
|
@ -39,36 +40,100 @@ describe 'Overland Batches API', type: :request do
|
|||
parameter name: :locations, in: :body, schema: {
|
||||
type: :object,
|
||||
properties: {
|
||||
type: { type: :string },
|
||||
type: { type: :string, example: 'Feature' },
|
||||
geometry: {
|
||||
type: :object,
|
||||
properties: {
|
||||
type: { type: :string },
|
||||
coordinates: { type: :array }
|
||||
type: { type: :string, example: 'Point' },
|
||||
coordinates: { type: :array, example: [13.356718, 52.502397] }
|
||||
}
|
||||
},
|
||||
properties: {
|
||||
type: :object,
|
||||
properties: {
|
||||
timestamp: { type: :string },
|
||||
altitude: { type: :number },
|
||||
speed: { type: :number },
|
||||
horizontal_accuracy: { type: :number },
|
||||
vertical_accuracy: { type: :number },
|
||||
motion: { type: :array },
|
||||
pauses: { type: :boolean },
|
||||
activity: { type: :string },
|
||||
desired_accuracy: { type: :number },
|
||||
deferred: { type: :number },
|
||||
significant_change: { type: :string },
|
||||
locations_in_payload: { type: :number },
|
||||
device_id: { type: :string },
|
||||
wifi: { type: :string },
|
||||
battery_state: { type: :string },
|
||||
battery_level: { type: :number }
|
||||
}
|
||||
},
|
||||
required: %w[geometry properties]
|
||||
timestamp: {
|
||||
type: :string,
|
||||
example: '2021-06-01T12:00:00Z',
|
||||
description: 'Timestamp in ISO 8601 format'
|
||||
},
|
||||
altitude: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'Altitude in meters'
|
||||
},
|
||||
speed: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'Speed in meters per second'
|
||||
},
|
||||
horizontal_accuracy: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'Horizontal accuracy in meters'
|
||||
},
|
||||
vertical_accuracy: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'Vertical accuracy in meters'
|
||||
},
|
||||
motion: {
|
||||
type: :array,
|
||||
example: %w[walking running driving cycling stationary],
|
||||
description: 'Motion type, for example: automotive_navigation, fitness, other_navigation or other'
|
||||
},
|
||||
activity: {
|
||||
type: :string,
|
||||
example: 'unknown',
|
||||
description: 'Activity type, for example: automotive_navigation, fitness, other_navigation or other'
|
||||
},
|
||||
desired_accuracy: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'Desired accuracy in meters'
|
||||
},
|
||||
deferred: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'the distance in meters to defer location updates'
|
||||
},
|
||||
significant_change: {
|
||||
type: :string,
|
||||
example: 'disabled',
|
||||
description: 'a significant change mode, disabled, enabled or exclusive'
|
||||
},
|
||||
locations_in_payload: {
|
||||
type: :number,
|
||||
example: 1,
|
||||
description: 'the number of locations in the payload'
|
||||
},
|
||||
device_id: {
|
||||
type: :string,
|
||||
example: 'iOS device #166',
|
||||
description: 'the device id'
|
||||
},
|
||||
unique_id: {
|
||||
type: :string,
|
||||
example: '1234567890',
|
||||
description: 'the device\'s Unique ID as set by Apple'
|
||||
},
|
||||
wifi: {
|
||||
type: :string,
|
||||
example: 'unknown',
|
||||
description: 'the WiFi network name'
|
||||
},
|
||||
battery_state: {
|
||||
type: :string,
|
||||
example: 'unknown',
|
||||
description: 'the battery state, unknown, unplugged, charging or full'
|
||||
},
|
||||
battery_level: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'the battery level percentage, from 0 to 1'
|
||||
}
|
||||
},
|
||||
required: %w[geometry properties]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,29 +39,29 @@ describe 'OwnTracks Points API', type: :request do
|
|||
parameter name: :point, in: :body, schema: {
|
||||
type: :object,
|
||||
properties: {
|
||||
batt: { type: :number },
|
||||
lon: { type: :number },
|
||||
acc: { type: :number },
|
||||
bs: { type: :number },
|
||||
inrids: { type: :array },
|
||||
BSSID: { type: :string },
|
||||
SSID: { type: :string },
|
||||
vac: { type: :number },
|
||||
inregions: { type: :array },
|
||||
lat: { type: :number },
|
||||
topic: { type: :string },
|
||||
t: { type: :string },
|
||||
conn: { type: :string },
|
||||
m: { type: :number },
|
||||
tst: { type: :number },
|
||||
alt: { type: :number },
|
||||
_type: { type: :string },
|
||||
tid: { type: :string },
|
||||
_http: { type: :boolean },
|
||||
ghash: { type: :string },
|
||||
isorcv: { type: :string },
|
||||
isotst: { type: :string },
|
||||
disptst: { type: :string }
|
||||
batt: { type: :number, description: 'Device battery level (percentage)' },
|
||||
lon: { type: :number, description: 'Longitude coordinate' },
|
||||
acc: { type: :number, description: 'Accuracy of position in meters' },
|
||||
bs: { type: :number, description: 'Battery status (0=unknown, 1=unplugged, 2=charging, 3=full)' },
|
||||
inrids: { type: :array, description: 'Array of region IDs device is currently in' },
|
||||
BSSID: { type: :string, description: 'Connected WiFi access point MAC address' },
|
||||
SSID: { type: :string, description: 'Connected WiFi network name' },
|
||||
vac: { type: :number, description: 'Vertical accuracy in meters' },
|
||||
inregions: { type: :array, description: 'Array of region names device is currently in' },
|
||||
lat: { type: :number, description: 'Latitude coordinate' },
|
||||
topic: { type: :string, description: 'MQTT topic in format owntracks/user/device' },
|
||||
t: { type: :string, description: 'Type of message (p=position, c=circle, etc)' },
|
||||
conn: { type: :string, description: 'Connection type (w=wifi, m=mobile, o=offline)' },
|
||||
m: { type: :number, description: 'Motion state (0=stopped, 1=moving)' },
|
||||
tst: { type: :number, description: 'Timestamp in Unix epoch time' },
|
||||
alt: { type: :number, description: 'Altitude in meters' },
|
||||
_type: { type: :string, description: 'Internal message type (usually "location")' },
|
||||
tid: { type: :string, description: 'Tracker ID used to display the initials of a user' },
|
||||
_http: { type: :boolean, description: 'Whether message was sent via HTTP (true) or MQTT (false)' },
|
||||
ghash: { type: :string, description: 'Geohash of location' },
|
||||
isorcv: { type: :string, description: 'ISO 8601 timestamp when message was received' },
|
||||
isotst: { type: :string, description: 'ISO 8601 timestamp of the location fix' },
|
||||
disptst: { type: :string, description: 'Human-readable timestamp of the location fix' }
|
||||
},
|
||||
required: %w[owntracks/jane]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,27 +101,73 @@ describe 'Points API', type: :request do
|
|||
geometry: {
|
||||
type: :object,
|
||||
properties: {
|
||||
type: { type: :string },
|
||||
coordinates: { type: :array, items: { type: :number } }
|
||||
type: {
|
||||
type: :string,
|
||||
example: 'Point',
|
||||
description: 'the geometry type, always Point'
|
||||
},
|
||||
coordinates: {
|
||||
type: :array,
|
||||
items: {
|
||||
type: :number,
|
||||
example: [-122.40530871, 37.74430413],
|
||||
description: 'the coordinates of the point, longitude and latitude'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
properties: {
|
||||
type: :object,
|
||||
properties: {
|
||||
timestamp: { type: :string },
|
||||
horizontal_accuracy: { type: :number },
|
||||
vertical_accuracy: { type: :number },
|
||||
altitude: { type: :number },
|
||||
speed: { type: :number },
|
||||
speed_accuracy: { type: :number },
|
||||
course: { type: :number },
|
||||
course_accuracy: { type: :number },
|
||||
track_id: { type: :string },
|
||||
device_id: { type: :string }
|
||||
timestamp: {
|
||||
type: :string,
|
||||
example: '2025-01-17T21:03:01Z',
|
||||
description: 'the timestamp of the point'
|
||||
},
|
||||
horizontal_accuracy: {
|
||||
type: :number,
|
||||
example: 5,
|
||||
description: 'the horizontal accuracy of the point in meters'
|
||||
},
|
||||
vertical_accuracy: {
|
||||
type: :number,
|
||||
example: -1,
|
||||
description: 'the vertical accuracy of the point in meters'
|
||||
},
|
||||
altitude: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'the altitude of the point in meters'
|
||||
},
|
||||
speed: {
|
||||
type: :number,
|
||||
example: 92.088,
|
||||
description: 'the speed of the point in meters per second'
|
||||
},
|
||||
speed_accuracy: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'the speed accuracy of the point in meters per second'
|
||||
},
|
||||
course_accuracy: {
|
||||
type: :number,
|
||||
example: 0,
|
||||
description: 'the course accuracy of the point in degrees'
|
||||
},
|
||||
track_id: {
|
||||
type: :string,
|
||||
example: '799F32F5-89BB-45FB-A639-098B1B95B09F',
|
||||
description: 'the track id of the point set by the device'
|
||||
},
|
||||
device_id: {
|
||||
type: :string,
|
||||
example: '8D5D4197-245B-4619-A88B-2049100ADE46',
|
||||
description: 'the device id of the point set by the device'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
required: %w[geometry properties]
|
||||
},
|
||||
required: %w[geometry properties]
|
||||
}
|
||||
}
|
||||
|
||||
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API Key'
|
||||
|
|
|
|||
|
|
@ -20,12 +20,26 @@ describe 'Settings API', type: :request do
|
|||
parameter name: :settings, in: :body, schema: {
|
||||
type: :object,
|
||||
properties: {
|
||||
route_opacity: { type: :number },
|
||||
meters_between_routes: { type: :number },
|
||||
minutes_between_routes: { type: :number },
|
||||
fog_of_war_meters: { type: :number },
|
||||
time_threshold_minutes: { type: :number },
|
||||
merge_threshold_minutes: { type: :number }
|
||||
route_opacity: {
|
||||
type: :number,
|
||||
example: 0.3,
|
||||
description: 'the opacity of the route, float between 0 and 1'
|
||||
},
|
||||
meters_between_routes: {
|
||||
type: :number,
|
||||
example: 100,
|
||||
description: 'the distance between routes in meters'
|
||||
},
|
||||
minutes_between_routes: {
|
||||
type: :number,
|
||||
example: 100,
|
||||
description: 'the time between routes in minutes'
|
||||
},
|
||||
fog_of_war_meters: {
|
||||
type: :number,
|
||||
example: 100,
|
||||
description: 'the fog of war distance in meters'
|
||||
}
|
||||
},
|
||||
optional: %w[route_opacity meters_between_routes minutes_between_routes fog_of_war_meters
|
||||
time_threshold_minutes merge_threshold_minutes]
|
||||
|
|
@ -49,12 +63,26 @@ describe 'Settings API', type: :request do
|
|||
settings: {
|
||||
type: :object,
|
||||
properties: {
|
||||
route_opacity: { type: :string },
|
||||
meters_between_routes: { type: :string },
|
||||
minutes_between_routes: { type: :string },
|
||||
fog_of_war_meters: { type: :string },
|
||||
time_threshold_minutes: { type: :string },
|
||||
merge_threshold_minutes: { type: :string }
|
||||
route_opacity: {
|
||||
type: :string,
|
||||
example: 0.3,
|
||||
description: 'the opacity of the route, float between 0 and 1'
|
||||
},
|
||||
meters_between_routes: {
|
||||
type: :string,
|
||||
example: 100,
|
||||
description: 'the distance between routes in meters'
|
||||
},
|
||||
minutes_between_routes: {
|
||||
type: :string,
|
||||
example: 100,
|
||||
description: 'the time between routes in minutes'
|
||||
},
|
||||
fog_of_war_meters: {
|
||||
type: :string,
|
||||
example: 100,
|
||||
description: 'the fog of war distance in meters'
|
||||
}
|
||||
},
|
||||
required: %w[route_opacity meters_between_routes minutes_between_routes fog_of_war_meters
|
||||
time_threshold_minutes merge_threshold_minutes]
|
||||
|
|
|
|||
|
|
@ -29,12 +29,20 @@ paths:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: Home
|
||||
description: The name of the area
|
||||
latitude:
|
||||
type: number
|
||||
example: 40.7128
|
||||
description: The latitude of the area
|
||||
longitude:
|
||||
type: number
|
||||
example: -74.006
|
||||
description: The longitude of the area
|
||||
radius:
|
||||
type: number
|
||||
example: 100
|
||||
description: The radius of the area in meters
|
||||
required:
|
||||
- name
|
||||
- latitude
|
||||
|
|
@ -71,14 +79,24 @@ paths:
|
|||
properties:
|
||||
id:
|
||||
type: integer
|
||||
example: 1
|
||||
description: The ID of the area
|
||||
name:
|
||||
type: string
|
||||
example: Home
|
||||
description: The name of the area
|
||||
latitude:
|
||||
type: number
|
||||
example: 40.7128
|
||||
description: The latitude of the area
|
||||
longitude:
|
||||
type: number
|
||||
example: -74.006
|
||||
description: The longitude of the area
|
||||
radius:
|
||||
type: number
|
||||
example: 100
|
||||
description: The radius of the area in meters
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
|
|
@ -117,6 +135,8 @@ paths:
|
|||
- name: api_key
|
||||
in: query
|
||||
required: true
|
||||
example: a1b2c3d4e5f6g7h8i9j0
|
||||
description: Your API authentication key
|
||||
schema:
|
||||
type: string
|
||||
- name: start_at
|
||||
|
|
@ -146,6 +166,23 @@ paths:
|
|||
data:
|
||||
type: array
|
||||
description: Array of countries and their visited cities
|
||||
example:
|
||||
- country: Germany
|
||||
cities:
|
||||
- city: Berlin
|
||||
points: 4394
|
||||
timestamp: 1724868369
|
||||
stayed_for: 24490
|
||||
- city: Munich
|
||||
points: 2156
|
||||
timestamp: 1724782369
|
||||
stayed_for: 12450
|
||||
- country: France
|
||||
cities:
|
||||
- city: Paris
|
||||
points: 3267
|
||||
timestamp: 1724695969
|
||||
stayed_for: 18720
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
|
|
@ -192,6 +229,27 @@ paths:
|
|||
responses:
|
||||
'200':
|
||||
description: Healthy
|
||||
headers:
|
||||
X-Dawarich-Response:
|
||||
type: string
|
||||
required: true
|
||||
example: Hey, I'm alive!
|
||||
description: Depending on the authentication status of the request,
|
||||
the response will be different. If the request is authenticated, the
|
||||
response will be 'Hey, I'm alive and authenticated!'. If the request
|
||||
is not authenticated, the response will be 'Hey, I'm alive!'.
|
||||
X-Dawarich-Version:
|
||||
type: string
|
||||
required: true
|
||||
example: 1.0.0
|
||||
description: 'The version of the application, for example: 1.0.0'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
"/api/v1/overland/batches":
|
||||
post:
|
||||
summary: Creates a batch of points
|
||||
|
|
@ -217,51 +275,97 @@ paths:
|
|||
properties:
|
||||
type:
|
||||
type: string
|
||||
example: Feature
|
||||
geometry:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
example: Point
|
||||
coordinates:
|
||||
type: array
|
||||
example:
|
||||
- 13.356718
|
||||
- 52.502397
|
||||
properties:
|
||||
type: object
|
||||
properties:
|
||||
timestamp:
|
||||
type: string
|
||||
example: '2021-06-01T12:00:00Z'
|
||||
description: Timestamp in ISO 8601 format
|
||||
altitude:
|
||||
type: number
|
||||
example: 0
|
||||
description: Altitude in meters
|
||||
speed:
|
||||
type: number
|
||||
example: 0
|
||||
description: Speed in meters per second
|
||||
horizontal_accuracy:
|
||||
type: number
|
||||
example: 0
|
||||
description: Horizontal accuracy in meters
|
||||
vertical_accuracy:
|
||||
type: number
|
||||
example: 0
|
||||
description: Vertical accuracy in meters
|
||||
motion:
|
||||
type: array
|
||||
pauses:
|
||||
type: boolean
|
||||
example:
|
||||
- walking
|
||||
- running
|
||||
- driving
|
||||
- cycling
|
||||
- stationary
|
||||
description: 'Motion type, for example: automotive_navigation,
|
||||
fitness, other_navigation or other'
|
||||
activity:
|
||||
type: string
|
||||
example: unknown
|
||||
description: 'Activity type, for example: automotive_navigation,
|
||||
fitness, other_navigation or other'
|
||||
desired_accuracy:
|
||||
type: number
|
||||
example: 0
|
||||
description: Desired accuracy in meters
|
||||
deferred:
|
||||
type: number
|
||||
example: 0
|
||||
description: the distance in meters to defer location updates
|
||||
significant_change:
|
||||
type: string
|
||||
example: disabled
|
||||
description: a significant change mode, disabled, enabled or
|
||||
exclusive
|
||||
locations_in_payload:
|
||||
type: number
|
||||
example: 1
|
||||
description: the number of locations in the payload
|
||||
device_id:
|
||||
type: string
|
||||
example: 'iOS device #166'
|
||||
description: the device id
|
||||
unique_id:
|
||||
type: string
|
||||
example: '1234567890'
|
||||
description: the device's Unique ID as set by Apple
|
||||
wifi:
|
||||
type: string
|
||||
example: unknown
|
||||
description: the WiFi network name
|
||||
battery_state:
|
||||
type: string
|
||||
example: unknown
|
||||
description: the battery state, unknown, unplugged, charging
|
||||
or full
|
||||
battery_level:
|
||||
type: number
|
||||
required:
|
||||
- geometry
|
||||
- properties
|
||||
example: 0
|
||||
description: the battery level percentage, from 0 to 1
|
||||
required:
|
||||
- geometry
|
||||
- properties
|
||||
examples:
|
||||
'0':
|
||||
summary: Creates a batch of points
|
||||
|
|
@ -286,7 +390,8 @@ paths:
|
|||
deferred: 0
|
||||
significant_change: unknown
|
||||
locations_in_payload: 1
|
||||
device_id: Swagger
|
||||
device_id: 'iOS device #166'
|
||||
unique_id: '1234567890'
|
||||
wifi: unknown
|
||||
battery_state: unknown
|
||||
battery_level: 0
|
||||
|
|
@ -315,50 +420,74 @@ paths:
|
|||
properties:
|
||||
batt:
|
||||
type: number
|
||||
description: Device battery level (percentage)
|
||||
lon:
|
||||
type: number
|
||||
description: Longitude coordinate
|
||||
acc:
|
||||
type: number
|
||||
description: Accuracy of position in meters
|
||||
bs:
|
||||
type: number
|
||||
description: Battery status (0=unknown, 1=unplugged, 2=charging,
|
||||
3=full)
|
||||
inrids:
|
||||
type: array
|
||||
description: Array of region IDs device is currently in
|
||||
BSSID:
|
||||
type: string
|
||||
description: Connected WiFi access point MAC address
|
||||
SSID:
|
||||
type: string
|
||||
description: Connected WiFi network name
|
||||
vac:
|
||||
type: number
|
||||
description: Vertical accuracy in meters
|
||||
inregions:
|
||||
type: array
|
||||
description: Array of region names device is currently in
|
||||
lat:
|
||||
type: number
|
||||
description: Latitude coordinate
|
||||
topic:
|
||||
type: string
|
||||
description: MQTT topic in format owntracks/user/device
|
||||
t:
|
||||
type: string
|
||||
description: Type of message (p=position, c=circle, etc)
|
||||
conn:
|
||||
type: string
|
||||
description: Connection type (w=wifi, m=mobile, o=offline)
|
||||
m:
|
||||
type: number
|
||||
description: Motion state (0=stopped, 1=moving)
|
||||
tst:
|
||||
type: number
|
||||
description: Timestamp in Unix epoch time
|
||||
alt:
|
||||
type: number
|
||||
description: Altitude in meters
|
||||
_type:
|
||||
type: string
|
||||
description: Internal message type (usually "location")
|
||||
tid:
|
||||
type: string
|
||||
description: Tracker ID used to display the initials of a user
|
||||
_http:
|
||||
type: boolean
|
||||
description: Whether message was sent via HTTP (true) or MQTT (false)
|
||||
ghash:
|
||||
type: string
|
||||
description: Geohash of location
|
||||
isorcv:
|
||||
type: string
|
||||
description: ISO 8601 timestamp when message was received
|
||||
isotst:
|
||||
type: string
|
||||
description: ISO 8601 timestamp of the location fix
|
||||
disptst:
|
||||
type: string
|
||||
description: Human-readable timestamp of the location fix
|
||||
required:
|
||||
- owntracks/jane
|
||||
examples:
|
||||
|
|
@ -725,36 +854,58 @@ paths:
|
|||
properties:
|
||||
type:
|
||||
type: string
|
||||
example: Point
|
||||
description: the geometry type, always Point
|
||||
coordinates:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
example:
|
||||
- -122.40530871
|
||||
- 37.74430413
|
||||
description: the coordinates of the point, longitude and latitude
|
||||
properties:
|
||||
type: object
|
||||
properties:
|
||||
timestamp:
|
||||
type: string
|
||||
example: '2025-01-17T21:03:01Z'
|
||||
description: the timestamp of the point
|
||||
horizontal_accuracy:
|
||||
type: number
|
||||
example: 5
|
||||
description: the horizontal accuracy of the point in meters
|
||||
vertical_accuracy:
|
||||
type: number
|
||||
example: -1
|
||||
description: the vertical accuracy of the point in meters
|
||||
altitude:
|
||||
type: number
|
||||
example: 0
|
||||
description: the altitude of the point in meters
|
||||
speed:
|
||||
type: number
|
||||
example: 92.088
|
||||
description: the speed of the point in meters per second
|
||||
speed_accuracy:
|
||||
type: number
|
||||
course:
|
||||
type: number
|
||||
example: 0
|
||||
description: the speed accuracy of the point in meters per second
|
||||
course_accuracy:
|
||||
type: number
|
||||
example: 0
|
||||
description: the course accuracy of the point in degrees
|
||||
track_id:
|
||||
type: string
|
||||
example: 799F32F5-89BB-45FB-A639-098B1B95B09F
|
||||
description: the track id of the point set by the device
|
||||
device_id:
|
||||
type: string
|
||||
required:
|
||||
- geometry
|
||||
- properties
|
||||
example: 8D5D4197-245B-4619-A88B-2049100ADE46
|
||||
description: the device id of the point set by the device
|
||||
required:
|
||||
- geometry
|
||||
- properties
|
||||
examples:
|
||||
'0':
|
||||
summary: Creates a batch of points
|
||||
|
|
@ -821,16 +972,20 @@ paths:
|
|||
properties:
|
||||
route_opacity:
|
||||
type: number
|
||||
example: 0.3
|
||||
description: the opacity of the route, float between 0 and 1
|
||||
meters_between_routes:
|
||||
type: number
|
||||
example: 100
|
||||
description: the distance between routes in meters
|
||||
minutes_between_routes:
|
||||
type: number
|
||||
example: 100
|
||||
description: the time between routes in minutes
|
||||
fog_of_war_meters:
|
||||
type: number
|
||||
time_threshold_minutes:
|
||||
type: number
|
||||
merge_threshold_minutes:
|
||||
type: number
|
||||
example: 100
|
||||
description: the fog of war distance in meters
|
||||
optional:
|
||||
- route_opacity
|
||||
- meters_between_routes
|
||||
|
|
@ -873,16 +1028,21 @@ paths:
|
|||
properties:
|
||||
route_opacity:
|
||||
type: string
|
||||
example: 0.3
|
||||
description: the opacity of the route, float between 0 and
|
||||
1
|
||||
meters_between_routes:
|
||||
type: string
|
||||
example: 100
|
||||
description: the distance between routes in meters
|
||||
minutes_between_routes:
|
||||
type: string
|
||||
example: 100
|
||||
description: the time between routes in minutes
|
||||
fog_of_war_meters:
|
||||
type: string
|
||||
time_threshold_minutes:
|
||||
type: string
|
||||
merge_threshold_minutes:
|
||||
type: string
|
||||
example: 100
|
||||
description: the fog of war distance in meters
|
||||
required:
|
||||
- route_opacity
|
||||
- meters_between_routes
|
||||
|
|
|
|||
Loading…
Reference in a new issue