updated trips
This commit is contained in:
103
main.py
103
main.py
@@ -226,30 +226,28 @@ class GetTripFromServer(Screen): # Renamed from HomeScreen
|
||||
else:
|
||||
self.ids.devices_spinner.background_color = (1, 1, 1, 1) # Reset to white if no valid device is selected
|
||||
|
||||
def open_date_picker(self):
|
||||
"""Open a popup to select a date."""
|
||||
def open_date_picker(self, which):
|
||||
"""Open a popup to select a date for start or end."""
|
||||
today = date.today()
|
||||
selected_date = [None] # Use a mutable object to store the selected date
|
||||
selected_date = [None]
|
||||
|
||||
def on_date_selected(instance):
|
||||
selected_date[0] = instance.text
|
||||
# Update the button text with the selected date
|
||||
self.ids.date_picker_button.text = f"Date: {today.year}-{today.month:02d}-{int(selected_date[0]):02d}"
|
||||
# Change the background color of the button to green
|
||||
self.ids.date_picker_button.background_color = (0.008, 0.525, 0.290, 1) # Green color (#02864A)
|
||||
print(f"Date selected: {self.ids.date_picker_button.text}")
|
||||
date_str = f"{today.year}-{today.month:02d}-{int(selected_date[0]):02d}"
|
||||
if which == 'start':
|
||||
self.ids.start_date_picker_button.text = date_str
|
||||
else:
|
||||
self.ids.end_date_picker_button.text = date_str
|
||||
popup.dismiss()
|
||||
|
||||
# Create a popup with a grid layout for the days
|
||||
layout = GridLayout(cols=7, spacing=5, padding=10)
|
||||
for day in range(1, 32): # Assuming a maximum of 31 days in a month
|
||||
for day in range(1, 32):
|
||||
try:
|
||||
current_date = date(today.year, today.month, day)
|
||||
button = Button(text=str(day), size_hint=(None, None), size=(40, 40))
|
||||
button.bind(on_press=on_date_selected)
|
||||
layout.add_widget(button)
|
||||
except ValueError:
|
||||
# Skip invalid dates (e.g., February 30)
|
||||
pass
|
||||
|
||||
popup = Popup(title="Select a Date", content=layout, size_hint=(0.8, 0.8))
|
||||
@@ -258,21 +256,92 @@ class GetTripFromServer(Screen): # Renamed from HomeScreen
|
||||
def get_trip_server_data(self):
|
||||
"""Handle the Get trip server data button press."""
|
||||
selected_device = self.ids.devices_spinner.text
|
||||
selected_date = self.ids.date_picker_button.text
|
||||
start_date = self.ids.start_date_picker_button.text
|
||||
end_date = self.ids.end_date_picker_button.text
|
||||
|
||||
if selected_device == "Loading devices..." or selected_device == "No devices found":
|
||||
print("No valid device selected.")
|
||||
self.ids.result_label.text = "Please select a valid device."
|
||||
return
|
||||
|
||||
if selected_date == "Select Date":
|
||||
if start_date == "Select Date" or end_date == "Select Date":
|
||||
print("No valid date selected.")
|
||||
self.ids.result_label.text = "Please select a valid date."
|
||||
self.ids.result_label.text = "Please select valid start and end dates."
|
||||
return
|
||||
|
||||
# Simulate fetching trip data from the server
|
||||
print(f"Fetching trip data for device: {selected_device} on date: {selected_date}")
|
||||
self.ids.result_label.text = f"Fetching trip data for {selected_device} on {selected_date}..."
|
||||
# Fetch trip data from the server
|
||||
print(f"Fetching trip data for device: {selected_device} from {start_date} to {end_date}")
|
||||
self.ids.result_label.text = f"Fetching trip data for {selected_device} from {start_date} to {end_date}..."
|
||||
|
||||
positions = self.fetch_positions_for_selected_day()
|
||||
if positions:
|
||||
print("Positions received:")
|
||||
for pos in positions:
|
||||
print(f"{pos['deviceTime']}: {pos['latitude']}, {pos['longitude']}")
|
||||
else:
|
||||
print("No positions found or error occurred.")
|
||||
|
||||
def fetch_positions_for_selected_day(self):
|
||||
"""Fetch all positions for the selected device and date/time range from the Traccar server."""
|
||||
settings = check_server_settings()
|
||||
if not settings:
|
||||
self.ids.result_label.text = "Server settings not found."
|
||||
return []
|
||||
|
||||
server_url = settings["server_url"]
|
||||
token = settings["token"]
|
||||
|
||||
selected_device = self.ids.devices_spinner.text
|
||||
if selected_device not in self.device_mapping:
|
||||
self.ids.result_label.text = "Please select a valid device."
|
||||
return []
|
||||
|
||||
device_id = self.device_mapping[selected_device]
|
||||
|
||||
# Get start/end date and hour from UI
|
||||
start_date = self.ids.start_date_picker_button.text
|
||||
start_hour = self.ids.start_hour_spinner.text
|
||||
end_date = self.ids.end_date_picker_button.text
|
||||
end_hour = self.ids.end_hour_spinner.text
|
||||
|
||||
# Validate
|
||||
if "Select" in start_date or "Select" in end_date:
|
||||
self.ids.result_label.text = "Please select both start and end dates."
|
||||
return []
|
||||
|
||||
# Build ISO 8601 time strings
|
||||
from_time = f"{start_date}T{start_hour}:00:00Z"
|
||||
to_time = f"{end_date}T{end_hour}:59:59Z"
|
||||
|
||||
# Prepare request for /reports/route
|
||||
url = f"{server_url}/reports/route"
|
||||
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
|
||||
params = {
|
||||
"deviceId": device_id,
|
||||
"from": from_time,
|
||||
"to": to_time
|
||||
}
|
||||
|
||||
try:
|
||||
print(f"Request Payload: {params}")
|
||||
response = requests.get(url, params=params, headers=headers, timeout=15)
|
||||
print(f"Response Status Code: {response.status_code}")
|
||||
print(f"Response Content: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
positions = response.json()
|
||||
print(f"Retrieved {len(positions)} positions.")
|
||||
self.ids.result_label.text = f"Retrieved {len(positions)} positions."
|
||||
return positions
|
||||
elif response.status_code == 400:
|
||||
self.ids.result_label.text = "Bad Request: Please check the request payload and token."
|
||||
return []
|
||||
else:
|
||||
self.ids.result_label.text = f"Failed: {response.status_code} - {response.reason}"
|
||||
return []
|
||||
except requests.exceptions.RequestException as e:
|
||||
self.ids.result_label.text = f"Error fetching positions: {str(e)}"
|
||||
return []
|
||||
|
||||
|
||||
class RegisterScreen(Screen):
|
||||
|
||||
@@ -1 +1 @@
|
||||
gAAAAABoPaPrItydUFVvwuzoJNOIF45pusZlJtW62JzZ74gfMb04ZfpUkkZq2Vl7TVSruG0_vH9b-ig_WFInrvwSTcxxN1hRN3Xz9yLdgZ_7qfE3qFS_KZpNtjW_5l9Fj5gpDAXJwX2v
|
||||
gAAAAABoPvmJa0okDG59jZQf9ZCFZ-qB7cFGQ18uF-duofQnBUYZncvyAG3OBhyB68lQQroIf8xRpHPGYtUy2jFMF1-bhvPkexBECo2BHz0Yun7w_gveksc05I0XKSR-tDvQuS3FKf_3
|
||||
@@ -1 +1 @@
|
||||
gAAAAABoPZo4DMcBt7anBtvn5wMfvWpsjR4Zi1BPdQhvnvSj0SyQmrQEF1uhsUjf0Y6Le3vBPKSplUypYURK_BUlJMbxUh2yI93KCcXdMJIy23TyNlVlt7dv1mPN3aQAAd4TqhA_dEVPAfBtT5ckcQAXqCRwd1RjRp06Qgz3XNHeLs14MxGet0rbWCLppopr6BTGulvbAdvCFoDqmRFYbfyWYlqqsN4-ZF0Q0qObOVPn7hqYHFTenK6tidi-JOx7Lx0jrCZWA2V0OgwCZOsTA-BYZeWK8RI2U645SJ_DBTBwK2avb6wDduJKOOIKJWKdUF5HaN3Ffc61KWxYO_8Eb21bYmNsDB31l9n-OgJLdzStT-WqLMmmw027YG_SZJsv-P2Ce0lCaw29s2Lbh_2VxWShJW6aDRxibZgHK3CoPajqR0MAkGJxT2w7pt7wT1zeMKHu51q3yPpV
|
||||
gAAAAABoPu5x585IL9U8GSHw4j-KQTpHJixfiwEHQf9KHR25D2fFcYDz6HrJzFP4U3iFxcV9dQQ1VhgDfDPO_nVDafVjMz9kiJdbp1KtiSyB8odqNmq1v6ZfLr_YXqzqNhMHfuA1zr4NgUkaivF-dQr84Z4WA4i1crmR-BA7tMIQti7rDjtmIxQATfKrNw1zD5yYrDiI2jOkUAGiJ1hIY0Ue-x0wmykzktwD_xIsixxX3IOeqgY39gZ7XmwRYA4boZsSbWqqmVDgjBElaUYCUKlp_t-50vHeMNySt5AHDwmY3cOb0zePMEVYzQiKMOTRsSMrAavnIquY6BHytWKOJuuOoWS5aTiuy1YGw6wMQZT7MFcza9u4iYjJm39cdLnGl4tWn8StvawbXepPFqrwcoJXAfkvd8f--eCPuAXIFi__EMM0jlO2PGSbj-5YjFnCdKspnycrlLB6
|
||||
1
t
Normal file
1
t
Normal file
@@ -0,0 +1 @@
|
||||
SDBGAiEA4sNXvVhL8w_Jd-5oCiXAuS5La5yelCQemfNysZYItaMCIQDOkzaoWKHbNnbZJw9ruGlsvbp35d90x3EGOZLXW_Gls3sidSI6MSwiZSI6IjIwMjUtMDYtMDlUMjE6MDA6MDAuMDAwKzAwOjAwIn0
|
||||
@@ -1,73 +1,41 @@
|
||||
import requests
|
||||
|
||||
def get_positions(server_url, token, device_ids, from_time, to_time):
|
||||
def get_device_route(server_url, token, device_id, from_time, to_time):
|
||||
"""
|
||||
Fetch position information from the Traccar server.
|
||||
|
||||
Args:
|
||||
server_url (str): The URL of the Traccar server.
|
||||
token (str): The authentication token.
|
||||
device_ids (list of int): List of device IDs.
|
||||
from_time (str): The start time in ISO 8601 format.
|
||||
to_time (str): The end time in ISO 8601 format.
|
||||
|
||||
Returns:
|
||||
list: The position information.
|
||||
Fetch all positions for a device in a time frame from Traccar server.
|
||||
"""
|
||||
if not device_ids or not from_time or not to_time:
|
||||
print("deviceId, from, and to are required parameters.")
|
||||
return None
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
url = f"{server_url}/positions"
|
||||
payload = {
|
||||
"deviceId": device_ids, # Send as list
|
||||
url = f"{server_url}/reports/route"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
params = {
|
||||
"deviceId": device_id,
|
||||
"from": from_time,
|
||||
"to": to_time
|
||||
}
|
||||
|
||||
try:
|
||||
print(f"Request Payload: {payload}")
|
||||
response = requests.get(url, params=payload, headers=headers)
|
||||
print(f"Response Status Code: {response.status_code}")
|
||||
print(f"Response Content: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
if response.status_code == 200:
|
||||
try:
|
||||
positions = response.json()
|
||||
print(f"Retrieved {len(positions)} positions:")
|
||||
for position in positions:
|
||||
print(position)
|
||||
print(f"Retrieved {len(positions)} positions.")
|
||||
return positions
|
||||
elif response.status_code == 400:
|
||||
print("Bad Request: Please check the request payload and token.")
|
||||
return None
|
||||
else:
|
||||
print(f"Failed to fetch positions: {response.status_code} - {response.reason}")
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching positions: {str(e)}")
|
||||
return None
|
||||
|
||||
|
||||
# Test the function
|
||||
if __name__ == "__main__":
|
||||
# Manually enter the server URL and token
|
||||
server_url = "https://gps.moto-adv.com/api"
|
||||
token = "RjBEAiB69jflCQJ9HQwGyFdAHF8J5JPMwIIclglbWiKMWeX6PwIgdBWc-YllE_-RwoQi7zX25WxQJqQX_OTIKOHk9a3mmBN7InUiOjEsImUiOiIyMDI1LTA2LTA4VDIxOjAwOjAwLjAwMCswMDowMCJ9"
|
||||
|
||||
device_id = input("Enter the device ID (required): ").strip()
|
||||
if not device_id:
|
||||
print("Device ID is required.")
|
||||
exit(1)
|
||||
device_ids = [int(device_id)]
|
||||
|
||||
# Set fixed time interval
|
||||
from_time = "2024-06-01T12:00:00Z"
|
||||
to_time = "2024-06-01T23:00:00Z"
|
||||
print(f"Using time interval: {from_time} to {to_time}")
|
||||
|
||||
positions = get_positions(server_url, token, device_ids, from_time, to_time)
|
||||
if positions:
|
||||
print("Position data retrieved successfully!")
|
||||
except Exception as e:
|
||||
print(f"Error parsing JSON: {e}")
|
||||
print(response.text)
|
||||
return []
|
||||
else:
|
||||
print("No position data found or an error occurred.")
|
||||
print(f"Failed to fetch positions: {response.status_code} - {response.text}")
|
||||
return []
|
||||
|
||||
# Example usage:
|
||||
if __name__ == "__main__":
|
||||
# Use your actual Traccar API endpoint (not /reports/route)
|
||||
server_url = "https://gps.moto-adv.com/api"
|
||||
token = "SDBGAiEA4sNXvVhL8w_Jd-5oCiXAuS5La5yelCQemfNysZYItaMCIQDOkzaoWKHbNnbZJw9ruGlsvbp35d90x3EGOZLXW_Gls3sidSI6MSwiZSI6IjIwMjUtMDYtMDlUMjE6MDA6MDAuMDAwKzAwOjAwIn0"
|
||||
device_id = 1 # Replace with your device ID
|
||||
from_time = "2024-06-02T21:00:00Z"
|
||||
to_time = "2025-06-03T20:59:00Z"
|
||||
positions = get_device_route(server_url, token, device_id, from_time, to_time)
|
||||
for pos in positions:
|
||||
print(f"{pos['deviceTime']}: {pos['latitude']}, {pos['longitude']}")
|
||||
64
traccar.kv
64
traccar.kv
@@ -227,7 +227,7 @@
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
size_hint_y: None
|
||||
height: 120 # Adjusted height for the frame
|
||||
height: 180 # Adjusted height for the frame
|
||||
spacing: 10
|
||||
padding: 10
|
||||
canvas.before:
|
||||
@@ -255,16 +255,64 @@
|
||||
values: [] # Initially empty
|
||||
size_hint: (0.5, None)
|
||||
height: 25
|
||||
font_size: 14 # Reduced font size
|
||||
on_text: root.on_device_selected(self.text) # Trigger background color change
|
||||
font_size: 14
|
||||
on_text: root.on_device_selected(self.text)
|
||||
|
||||
# New row: Starting date and hour
|
||||
BoxLayout:
|
||||
orientation: "horizontal"
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
spacing: 10
|
||||
|
||||
Label:
|
||||
text: "Starting Date"
|
||||
size_hint_x: 0.3
|
||||
font_size: 14
|
||||
|
||||
Button:
|
||||
id: date_picker_button
|
||||
text: "Select Date"
|
||||
size_hint: (0.5, None)
|
||||
id: start_date_picker_button
|
||||
text: "Select Start Date"
|
||||
size_hint_x: 0.4
|
||||
height: 25
|
||||
font_size: 14 # Reduced font size
|
||||
on_press: root.open_date_picker()
|
||||
font_size: 14
|
||||
on_press: root.open_date_picker('start')
|
||||
|
||||
Spinner:
|
||||
id: start_hour_spinner
|
||||
text: "00"
|
||||
values: [f"{i:02d}" for i in range(24)]
|
||||
size_hint_x: 0.2
|
||||
height: 25
|
||||
font_size: 14
|
||||
|
||||
# New row: End date and hour
|
||||
BoxLayout:
|
||||
orientation: "horizontal"
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
spacing: 10
|
||||
|
||||
Label:
|
||||
text: "End Date"
|
||||
size_hint_x: 0.3
|
||||
font_size: 14
|
||||
|
||||
Button:
|
||||
id: end_date_picker_button
|
||||
text: "Select End Date"
|
||||
size_hint_x: 0.4
|
||||
height: 25
|
||||
font_size: 14
|
||||
on_press: root.open_date_picker('end')
|
||||
|
||||
Spinner:
|
||||
id: end_hour_spinner
|
||||
text: "23"
|
||||
values: [f"{i:02d}" for i in range(24)]
|
||||
size_hint_x: 0.2
|
||||
height: 25
|
||||
font_size: 14
|
||||
|
||||
# New row: Get trip server data button
|
||||
Button:
|
||||
|
||||
Reference in New Issue
Block a user