diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json
index 525472c..497cff1 100755
--- a/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json
+++ b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json
@@ -19,6 +19,7 @@
{
"fieldname": "tracker",
"fieldtype": "Link",
+ "in_list_view": 1,
"label": "Tracker",
"options": "Tracker"
},
@@ -58,7 +59,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2024-04-11 15:29:47.121435",
+ "modified": "2024-04-17 12:10:38.738798",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Fleet Vehicle",
diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle_dashboard.py b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle_dashboard.py
new file mode 100644
index 0000000..cccce3b
--- /dev/null
+++ b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle_dashboard.py
@@ -0,0 +1,14 @@
+from frappe import _
+
+def get_data():
+ return {
+ 'heatmap': False,
+ 'heatmap_message': _('Based on routes (trips) of linked Vehicle.'),
+ 'fieldname': 'fleet_vehicle',
+ 'transactions': [
+ {
+ 'label': _('Available Routes'),
+ 'items': ['Trip']
+ }
+ ]
+ }
diff --git a/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json
index b2eb83d..1849f33 100755
--- a/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json
+++ b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json
@@ -8,8 +8,7 @@
"engine": "InnoDB",
"field_order": [
"traccar_server",
- "traccar_username",
- "traccar_password"
+ "traccar_token"
],
"fields": [
{
@@ -18,20 +17,17 @@
"label": "URL Server"
},
{
- "fieldname": "traccar_username",
- "fieldtype": "Data",
- "label": "Username"
- },
- {
- "fieldname": "traccar_password",
+ "fieldname": "traccar_token",
"fieldtype": "Password",
- "label": "Password"
+ "in_list_view": 1,
+ "label": "Token",
+ "reqd": 1
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2024-04-11 16:50:20.436522",
+ "modified": "2024-04-16 11:46:08.967177",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Traccar Settings",
diff --git a/fleet_management/fleet_management/doctype/tracker/tracker.json b/fleet_management/fleet_management/doctype/tracker/tracker.json
index 7e021ca..8aba04f 100755
--- a/fleet_management/fleet_management/doctype/tracker/tracker.json
+++ b/fleet_management/fleet_management/doctype/tracker/tracker.json
@@ -18,8 +18,7 @@
"model",
"contact",
"category",
- "disabled",
- "button_trips"
+ "disabled"
],
"fields": [
{
@@ -86,16 +85,11 @@
"fieldname": "disabled",
"fieldtype": "Data",
"label": "Disabled"
- },
- {
- "fieldname": "button_trips",
- "fieldtype": "Button",
- "label": "View Trips"
}
],
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2024-04-11 12:52:37.199851",
+ "modified": "2024-04-17 12:10:01.016561",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Tracker",
diff --git a/fleet_management/fleet_management/doctype/trip/trip.json b/fleet_management/fleet_management/doctype/trip/trip.json
index 61fbdeb..a9ec740 100755
--- a/fleet_management/fleet_management/doctype/trip/trip.json
+++ b/fleet_management/fleet_management/doctype/trip/trip.json
@@ -16,12 +16,18 @@
"average_speed",
"max_speed",
"spent_fuel",
+ "start_position_id",
+ "start_lat",
+ "start_lon",
+ "end_lat",
+ "end_lon",
"start_address",
"end_address",
"duration",
"driver_unique_id",
"fleet_vehicle",
- "tracker"
+ "tracker",
+ "unique_id"
],
"fields": [
{
@@ -105,11 +111,42 @@
"fieldtype": "Link",
"label": "Tracker",
"options": "Tracker"
+ },
+ {
+ "fieldname": "unique_id",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "unique_id"
+ },
+ {
+ "fieldname": "start_position_id",
+ "fieldtype": "Data",
+ "label": "Start Position ID"
+ },
+ {
+ "fieldname": "start_lat",
+ "fieldtype": "Data",
+ "label": "Start Latitude"
+ },
+ {
+ "fieldname": "start_lon",
+ "fieldtype": "Data",
+ "label": "Start Longitude"
+ },
+ {
+ "fieldname": "end_lat",
+ "fieldtype": "Data",
+ "label": "End Latitude"
+ },
+ {
+ "fieldname": "end_lon",
+ "fieldtype": "Data",
+ "label": "End Longitude"
}
],
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2024-04-12 12:31:26.524755",
+ "modified": "2024-04-14 17:20:36.937514",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Trip",
diff --git a/fleet_management/fleet_management/workspace/fleet_management/fleet_management.json b/fleet_management/fleet_management/workspace/fleet_management/fleet_management.json
new file mode 100644
index 0000000..96796e1
--- /dev/null
+++ b/fleet_management/fleet_management/workspace/fleet_management/fleet_management.json
@@ -0,0 +1,63 @@
+{
+ "charts": [],
+ "content": "[{\"id\":\"PROwwE8CMR\",\"type\":\"header\",\"data\":{\"text\":\"Fleet Management\",\"col\":12}},{\"id\":\"zW5zgDOYYt\",\"type\":\"custom_block\",\"data\":{\"custom_block_name\":\"Traccar Button\",\"col\":12}},{\"id\":\"jqsG9hjyOU\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Tracker Devices\",\"col\":4}},{\"id\":\"0ABxSuv34v\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trips\",\"col\":3}},{\"id\":\"0s-UKXtLZr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Traccar Server Settings\",\"col\":5}},{\"id\":\"dHKqoHT70w\",\"type\":\"quick_list\",\"data\":{\"quick_list_name\":\"Fleet Vehicle\",\"col\":11}}]",
+ "creation": "2024-04-14 17:22:37.053886",
+ "custom_blocks": [
+ {
+ "custom_block_name": "Traccar Button",
+ "label": "Traccar Button"
+ }
+ ],
+ "docstatus": 0,
+ "doctype": "Workspace",
+ "for_user": "",
+ "hide_custom": 0,
+ "icon": "map",
+ "idx": 1,
+ "is_hidden": 0,
+ "label": "Fleet Management",
+ "links": [],
+ "modified": "2024-04-16 12:06:30.954320",
+ "modified_by": "Administrator",
+ "module": "Fleet Management",
+ "name": "Fleet Management",
+ "number_cards": [],
+ "owner": "Administrator",
+ "parent_page": "",
+ "public": 1,
+ "quick_lists": [
+ {
+ "document_type": "Fleet Vehicle",
+ "label": "Fleet Vehicle",
+ "quick_list_filter": "[]"
+ }
+ ],
+ "roles": [],
+ "sequence_id": 4.1,
+ "shortcuts": [
+ {
+ "color": "Grey",
+ "doc_view": "List",
+ "label": "Tracker Devices",
+ "link_to": "Tracker",
+ "stats_filter": "[]",
+ "type": "DocType"
+ },
+ {
+ "color": "Grey",
+ "doc_view": "List",
+ "label": "Trips",
+ "link_to": "Trip",
+ "stats_filter": "[]",
+ "type": "DocType"
+ },
+ {
+ "color": "Grey",
+ "doc_view": "List",
+ "label": "Traccar Server Settings",
+ "link_to": "Traccar Settings",
+ "type": "DocType"
+ }
+ ],
+ "title": "Fleet Management"
+}
\ No newline at end of file
diff --git a/fleet_management/hooks.py b/fleet_management/hooks.py
index 0ee443f..e57c27a 100755
--- a/fleet_management/hooks.py
+++ b/fleet_management/hooks.py
@@ -218,3 +218,13 @@ app_license = "GPLv3"
# hooks.py
+scheduler_events = {
+ #"all": [
+ # "fleet_management.tasks.get_trips_for_device"
+ #],
+ "cron": {
+ "*/15 * * * *": [
+ "fleet_management.tasks.get_trips_for_device"
+ ]
+ }
+}
diff --git a/fleet_management/tasks.py b/fleet_management/tasks.py
new file mode 100755
index 0000000..1d50db6
--- /dev/null
+++ b/fleet_management/tasks.py
@@ -0,0 +1,107 @@
+from datetime import datetime, timedelta
+from zoneinfo import ZoneInfo
+from frappe.utils.password import get_decrypted_password
+from frappe.utils import add_to_date, get_datetime
+import frappe
+import requests
+
+def traccar_auth(ts):
+ """authenticates on traccar server and returns cookies"""
+ response = requests.get(
+ f"{ts.traccar_server}/api/session",
+ params = {
+ 'token': get_decrypted_password('Traccar Settings', ts.name, 'traccar_token')
+ }
+ )
+
+ if response.status_code == 200:
+ return response.cookies
+ else:
+ frappe.throw(f"Authentication failed: {response.status_code}: {response.reason}
Dict ts: {ts.as_dict()}")
+
+def get_devices():
+ ts = frappe.get_doc('Traccar Settings')
+
+ try:
+ devices_response = requests.get(
+ f"{ts.traccar_server}/api/devices",
+ cookies=traccar_auth(ts)
+ )
+ devices_response.raise_for_status()
+
+ except requests.HTTPError as e:
+ frappe.throw(f"HTTP error occurred: {e}")
+ except Exception as e:
+ frappe.throw(f"Error fetching devices: {e}")
+
+ return devices_response.json()
+
+
+@frappe.whitelist()
+def get_trips_for_device():
+ ts = frappe.get_doc('Traccar Settings')
+ frappe.logger().info("Starting import Trips from Traccar server ...")
+ for dev in get_devices():
+ try:
+ trips_response = requests.get(
+ f"{ts.traccar_server}/api/reports/trips",
+ cookies=traccar_auth(ts),
+ params={
+ 'deviceId': dev['id'],
+ 'from': (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%dT23:00:00.000Z'),
+ 'to': datetime.now().strftime('%Y-%m-%dT22:59:59.999Z')
+ }
+ )
+ trips_response.raise_for_status()
+ except requests.HTTPError as e:
+ frappe.throw(f"HTTP error occurred: {e}")
+ except Exception as e:
+ frappe.throw(f"Error fetching trips: {e}")
+
+ #if len(trips_response.json()) > 0:
+ # for debug in trips_response.json():
+ # print(f"Distance: {debug['distance']} | Average Speed: {debug['averageSpeed']}")
+
+ for trip in trips_response.json():
+ # Assuming 'device_id' and 'startTime' can uniquely identify a trip
+ unique_id = f"{trip['deviceId']}-{trip['startTime']}"
+
+ # Check if the document already exists
+ existing_trip = frappe.db.exists('Trip', {'unique_id': unique_id})
+
+ if existing_trip:
+ trip_doc = frappe.get_doc('Trip', existing_trip)
+ else:
+ trip_doc = frappe.new_doc('Trip')
+ trip_doc.unique_id = unique_id # Atribui o identificador Ășnico
+
+ # Atualiza ou define os campos
+ trip_doc.device_id = trip['deviceId']
+ trip_doc.start = datetime.fromisoformat(trip['startTime']).replace(
+ tzinfo=ZoneInfo("UTC")).astimezone(ZoneInfo("Europe/Berlin")
+ ).strftime('%Y-%m-%d %H:%M:%S')
+ trip_doc.end = datetime.fromisoformat(trip['endTime']).replace(
+ tzinfo=ZoneInfo("UTC")).astimezone(ZoneInfo("Europe/Berlin")
+ ).strftime('%Y-%m-%d %H:%M:%S')
+ trip_doc.distance = trip['distance']
+ trip_doc.average_speed = trip['averageSpeed']
+ trip_doc.max_speed = trip['maxSpeed']
+ trip_doc.spent_fuel = trip['spentFuel']
+ trip_doc.start_position_id = trip['startPositionId']
+ trip_doc.end_position_id = trip['endPositionId']
+ trip_doc.start_lat = trip['startLat']
+ trip_doc.start_lon = trip['startLon']
+ trip_doc.end_lat = trip['endLat']
+ trip_doc.end_lon = trip['endLon']
+ trip_doc.start_address = trip['startAddress']
+ trip_doc.end_address = trip['endAddress']
+ trip_doc.duration = trip['duration']
+ trip_doc.driver_unique_id = trip['driverUniqueId']
+ trip_doc.tracker = frappe.get_value('Tracker', {'portal_id': trip['deviceId']}, 'portal_name')
+ trip_doc.fleet_vehicle = frappe.get_value('Fleet Vehicle', {'tracker': trip_doc.tracker}, 'name')
+
+ trip_doc.save(ignore_permissions=True)
+
+ frappe.db.commit()
+
+ frappe.logger().info("End of task of import")
diff --git a/fleet_management/traccar_api.py b/fleet_management/traccar_api.py
index fe96f36..249eec2 100755
--- a/fleet_management/traccar_api.py
+++ b/fleet_management/traccar_api.py
@@ -1,4 +1,5 @@
from datetime import datetime, timedelta
+from zoneinfo import ZoneInfo
from frappe.utils.password import get_decrypted_password
import frappe
import requests
@@ -6,11 +7,10 @@ import requests
def traccar_auth(ts):
"""authenticates on traccar server and returns cookies"""
- response = requests.post(
+ response = requests.get(
f"{ts.traccar_server}/api/session",
- data = {
- 'email': ts.traccar_username,
- 'password': get_decrypted_password('Traccar Settings', ts.name, 'traccar_password')
+ params = {
+ 'token': get_decrypted_password('Traccar Settings', ts.name, 'traccar_token')
}
)
@@ -123,11 +123,14 @@ def get_trips_for_device(device_id, start=None, end=None):
def getroutes(name, start=None, end=None):
ts = frappe.get_doc('Traccar Settings')
device_id = frappe.get_value('Trip', {'name': name}, 'device_id')
- startdate = datetime.strptime(start, "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
- enddate = datetime.strptime(end, "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
-
- print(f"startdate: {startdate}")
- print(f"enddate: {enddate}")
+ startdate = datetime.strptime(start, "%Y-%m-%d %H:%M:%S")\
+ .replace(tzinfo=ZoneInfo("Europe/Berlin"))\
+ .astimezone(ZoneInfo("UTC"))\
+ .strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
+ enddate = datetime.strptime(end, "%Y-%m-%d %H:%M:%S")\
+ .replace(tzinfo=ZoneInfo("Europe/Berlin"))\
+ .astimezone(ZoneInfo("UTC"))\
+ .strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
# get route by filter from traccar server
try:
@@ -147,3 +150,9 @@ def getroutes(name, start=None, end=None):
return route_response.json()
+@frappe.whitelist()
+def get_traccar_url():
+ ts = frappe.get_doc('Traccar Settings')
+
+ return(f"{ts.traccar_server}/?token=" + get_decrypted_password('Traccar Settings', ts.name, 'traccar_token'))
+