smartfleet-optimizer 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ MIT License
2
+ Copyright (c) 2025 Satvik T M
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software to deal in the Software without restriction.
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: smartfleet-optimizer
3
+ Version: 0.1.0
4
+ Summary: Analytics library for fleet telemetry: risk scoring, alerts, maintenance prediction
5
+ Author: Satvik T M
6
+ Author-email: satvikw007@gmail.com
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: classifier
16
+ Dynamic: description
17
+ Dynamic: description-content-type
18
+ Dynamic: license-file
19
+ Dynamic: requires-python
20
+ Dynamic: summary
21
+
22
+ # fleet-optimization-engine-satvik25159712
23
+
24
+ Analytics library for fleet telemetry data. Provides risk scoring,
25
+ alert detection, fuel efficiency analysis and maintenance prediction.
26
+
27
+ ## Install
28
+ pip install fleet-optimization-engine-satvik25159712
29
+
30
+ ## Quick start
31
+ from fleet_optimization_pkg import TelemetryAnalyzer
32
+ analyzer = TelemetryAnalyzer()
33
+ profile = analyzer.build_risk_profile({
34
+ "vehicle_id": "VAN-001", "speed_kmh": 50,
35
+ "fuel_percent": 75, "engine_temp_c": 85
36
+ })
37
+ print(profile.risk_label)
@@ -0,0 +1,16 @@
1
+ # fleet-optimization-engine-satvik25159712
2
+
3
+ Analytics library for fleet telemetry data. Provides risk scoring,
4
+ alert detection, fuel efficiency analysis and maintenance prediction.
5
+
6
+ ## Install
7
+ pip install fleet-optimization-engine-satvik25159712
8
+
9
+ ## Quick start
10
+ from fleet_optimization_pkg import TelemetryAnalyzer
11
+ analyzer = TelemetryAnalyzer()
12
+ profile = analyzer.build_risk_profile({
13
+ "vehicle_id": "VAN-001", "speed_kmh": 50,
14
+ "fuel_percent": 75, "engine_temp_c": 85
15
+ })
16
+ print(profile.risk_label)
@@ -0,0 +1,5 @@
1
+ from .analyzer import TelemetryAnalyzer
2
+ from .models import AlertSeverity, FleetAlert, VehicleRiskProfile
3
+
4
+ __version__ = "0.1.0"
5
+ __all__ = ["TelemetryAnalyzer", "AlertSeverity", "FleetAlert", "VehicleRiskProfile"]
@@ -0,0 +1,156 @@
1
+ """
2
+ analyzer.py
3
+ Stateless analytics engine for fleet telemetry data.
4
+ Called by the Lambda function each time a telemetry reading
5
+ arrives from SQS.
6
+ """
7
+ from .models import AlertSeverity, FleetAlert, VehicleRiskProfile
8
+
9
+ # Thresholds
10
+ ENGINE_TEMP_WARNING = 100.0
11
+ ENGINE_TEMP_CRITICAL = 110.0
12
+ FUEL_WARNING = 20.0
13
+ FUEL_CRITICAL = 10.0
14
+ SPEED_WARNING = 100.0
15
+ SPEED_CRITICAL = 110.0
16
+ MAINTENANCE_TEMP = 95.0
17
+ MAINTENANCE_FUEL = 25.0
18
+
19
+
20
+ class TelemetryAnalyzer:
21
+ """
22
+ Processes raw telemetry dicts into structured risk assessments.
23
+
24
+ All methods are stateless so this class is safe for use in
25
+ AWS Lambda which may create new instances at any time.
26
+ """
27
+
28
+ def build_risk_profile(self, reading):
29
+ """
30
+ Main method. Runs all analyses and returns a VehicleRiskProfile.
31
+ """
32
+ return VehicleRiskProfile(
33
+ vehicle_id = reading.get("vehicle_id", "UNKNOWN"),
34
+ risk_score = self.calculate_risk_score(reading),
35
+ alerts = self.detect_alerts(reading),
36
+ fuel_efficiency_score = self.calculate_fuel_efficiency_score(reading),
37
+ maintenance_due = self.predict_maintenance_needed(reading),
38
+ )
39
+
40
+ def calculate_risk_score(self, reading):
41
+ """
42
+ Weighted composite risk score 0-100.
43
+ Returns (float) Score in range 0.0 to 100.0
44
+ """
45
+ temp = reading.get("engine_temp_c", 80.0)
46
+ fuel = reading.get("fuel_percent", 100.0)
47
+ speed = reading.get("speed_kmh", 0.0)
48
+
49
+ # Engine temperature component
50
+ if temp >= ENGINE_TEMP_CRITICAL:
51
+ temp_risk = 100.0
52
+ elif temp >= ENGINE_TEMP_WARNING:
53
+ temp_risk = ((temp - ENGINE_TEMP_WARNING) /
54
+ (ENGINE_TEMP_CRITICAL - ENGINE_TEMP_WARNING)) * 100
55
+ else:
56
+ temp_risk = 0.0
57
+
58
+ # Fuel component, low fuel = high risk
59
+ if fuel <= FUEL_CRITICAL:
60
+ fuel_risk = 100.0
61
+ elif fuel <= FUEL_WARNING:
62
+ fuel_risk = ((FUEL_WARNING - fuel) /
63
+ (FUEL_WARNING - FUEL_CRITICAL)) * 100
64
+ else:
65
+ fuel_risk = 0.0
66
+
67
+ # Speed component
68
+ if speed >= SPEED_CRITICAL:
69
+ speed_risk = 100.0
70
+ elif speed >= SPEED_WARNING:
71
+ speed_risk = ((speed - SPEED_WARNING) /
72
+ (SPEED_CRITICAL - SPEED_WARNING)) * 100
73
+ else:
74
+ speed_risk = 0.0
75
+
76
+ return round(min(100.0, (temp_risk * 0.4) +
77
+ (fuel_risk * 0.3) +
78
+ (speed_risk * 0.3)), 2)
79
+
80
+ def detect_alerts(self, reading):
81
+ """
82
+ Check all thresholds and return a list of FleetAlert objects.
83
+ """
84
+ alerts = []
85
+ vid = reading.get("vehicle_id", "UNKNOWN")
86
+ temp = reading.get("engine_temp_c", 80.0)
87
+ fuel = reading.get("fuel_percent", 100.0)
88
+ speed = reading.get("speed_kmh", 0.0)
89
+
90
+ # Engine temperature checks
91
+ if temp >= ENGINE_TEMP_CRITICAL:
92
+ alerts.append(FleetAlert(
93
+ vid, "HIGH_ENGINE_TEMP", AlertSeverity.CRITICAL,
94
+ f"Engine temp {temp:.1f}C is critical — stop vehicle immediately.",
95
+ temp, ENGINE_TEMP_CRITICAL))
96
+ elif temp >= ENGINE_TEMP_WARNING:
97
+ alerts.append(FleetAlert(
98
+ vid, "HIGH_ENGINE_TEMP", AlertSeverity.WARNING,
99
+ f"Engine temp {temp:.1f}C exceeds warning threshold.",
100
+ temp, ENGINE_TEMP_WARNING))
101
+
102
+ # Fuel level checks
103
+ if fuel <= FUEL_CRITICAL:
104
+ alerts.append(FleetAlert(
105
+ vid, "LOW_FUEL", AlertSeverity.CRITICAL,
106
+ f"Fuel critically low at {fuel:.1f}% — refuel immediately.",
107
+ fuel, FUEL_CRITICAL))
108
+ elif fuel <= FUEL_WARNING:
109
+ alerts.append(FleetAlert(
110
+ vid, "LOW_FUEL", AlertSeverity.WARNING,
111
+ f"Fuel at {fuel:.1f}% — plan refuel soon.",
112
+ fuel, FUEL_WARNING))
113
+
114
+ # Speed checks
115
+ if speed >= SPEED_CRITICAL:
116
+ alerts.append(FleetAlert(
117
+ vid, "SPEEDING", AlertSeverity.CRITICAL,
118
+ f"Vehicle speeding at {speed:.1f} km/h.",
119
+ speed, SPEED_CRITICAL))
120
+ elif speed >= SPEED_WARNING:
121
+ alerts.append(FleetAlert(
122
+ vid, "SPEEDING", AlertSeverity.WARNING,
123
+ f"Approaching speed limit at {speed:.1f} km/h.",
124
+ speed, SPEED_WARNING))
125
+
126
+ return alerts
127
+
128
+ def calculate_fuel_efficiency_score(self, reading):
129
+ """
130
+ Fuel efficiency index 0-100. Higher = more efficient.
131
+ """
132
+ speed = reading.get("speed_kmh", 0.0)
133
+ fuel = reading.get("fuel_percent", 100.0)
134
+ if speed == 0:
135
+ return 100.0
136
+ estimated_drain = speed * 0.25
137
+ return round(min(100.0, (fuel / max(estimated_drain, 1.0)) * 10), 2)
138
+
139
+ def predict_maintenance_needed(self, reading):
140
+ """
141
+ Returns True if the vehicle likely needs maintenance soon.
142
+ """
143
+ return (reading.get("engine_temp_c", 80.0) > MAINTENANCE_TEMP and
144
+ reading.get("fuel_percent", 100.0) < MAINTENANCE_FUEL)
145
+
146
+ def classify_alert_severity(self, alerts):
147
+ """
148
+ Return the highest severity level from a list of alerts.
149
+ """
150
+ if not alerts:
151
+ return AlertSeverity.INFO
152
+ if any(a.severity == AlertSeverity.CRITICAL for a in alerts):
153
+ return AlertSeverity.CRITICAL
154
+ if any(a.severity == AlertSeverity.WARNING for a in alerts):
155
+ return AlertSeverity.WARNING
156
+ return AlertSeverity.INFO
@@ -0,0 +1,89 @@
1
+ """
2
+ models.py
3
+ Data models for the fleet optimization engine.
4
+ AlertSeverity, FleetAlert and VehicleRiskProfile are used by
5
+ TelemetryAnalyzer and consumed by the Django app and Lambda function.
6
+ """
7
+ from enum import Enum
8
+
9
+
10
+ class AlertSeverity(Enum):
11
+ """
12
+ Severity levels for fleet alerts.
13
+ """
14
+ INFO = "INFO"
15
+ WARNING = "WARNING"
16
+ CRITICAL = "CRITICAL"
17
+
18
+
19
+ class FleetAlert:
20
+ """
21
+ A single threshold breach for one vehicle.
22
+
23
+ Attributes:
24
+ vehicle_id (str): Which vehicle triggered the alert
25
+ alert_type (str): Category e.g. HIGH_ENGINE_TEMP, LOW_FUEL, SPEEDING
26
+ severity (AlertSeverity): How urgent this alert is
27
+ message (str): Human-readable description for the fleet manager
28
+ value (float): The actual sensor value that triggered the alert
29
+ threshold (float): The threshold that was breached
30
+ """
31
+ def __init__(self, vehicle_id, alert_type, severity,
32
+ message, value, threshold):
33
+ self.vehicle_id = vehicle_id
34
+ self.alert_type = alert_type
35
+ self.severity = severity
36
+ self.message = message
37
+ self.value = value
38
+ self.threshold = threshold
39
+
40
+ def to_dict(self):
41
+ """Serialise to dict for JSON encoding or DynamoDB storage."""
42
+ return {
43
+ "vehicle_id": self.vehicle_id,
44
+ "alert_type": self.alert_type,
45
+ "severity": self.severity.value,
46
+ "message": self.message,
47
+ "value": self.value,
48
+ "threshold": self.threshold,
49
+ }
50
+
51
+ def __repr__(self):
52
+ return (f"FleetAlert({self.severity.value}: {self.alert_type} "
53
+ f"for {self.vehicle_id}, value={self.value})")
54
+
55
+
56
+ class VehicleRiskProfile:
57
+ """
58
+ Composite risk assessment for a single vehicle reading.
59
+ """
60
+ def __init__(self, vehicle_id, risk_score, alerts,
61
+ fuel_efficiency_score, maintenance_due):
62
+ self.vehicle_id = vehicle_id
63
+ self.risk_score = round(risk_score, 2)
64
+ self.risk_label = self._label(risk_score)
65
+ self.alerts = alerts
66
+ self.fuel_efficiency_score = round(fuel_efficiency_score, 2)
67
+ self.maintenance_due = maintenance_due
68
+
69
+ @staticmethod
70
+ def _label(score):
71
+ """Map numeric score to a human-readable risk band."""
72
+ if score >= 75: return "CRITICAL"
73
+ if score >= 50: return "HIGH"
74
+ if score >= 25: return "MEDIUM"
75
+ return "LOW"
76
+
77
+ def to_dict(self):
78
+ return {
79
+ "vehicle_id": self.vehicle_id,
80
+ "risk_score": self.risk_score,
81
+ "risk_label": self.risk_label,
82
+ "alerts": [a.to_dict() for a in self.alerts],
83
+ "fuel_efficiency_score": self.fuel_efficiency_score,
84
+ "maintenance_due": self.maintenance_due,
85
+ }
86
+
87
+ def __repr__(self):
88
+ return (f"VehicleRiskProfile({self.vehicle_id}: {self.risk_label} "
89
+ f"score={self.risk_score}, alerts={len(self.alerts)})")
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,22 @@
1
+ import setuptools
2
+
3
+ with open("README.md", "r", encoding="utf-8") as fh:
4
+ long_description = fh.read()
5
+
6
+ setuptools.setup(
7
+ name="smartfleet-optimizer",
8
+ version="0.1.0",
9
+ author="Satvik T M",
10
+ author_email="satvikw007@gmail.com",
11
+ description="Analytics library for fleet telemetry: risk scoring, alerts, maintenance prediction",
12
+ long_description=long_description,
13
+ long_description_content_type="text/markdown",
14
+ packages=setuptools.find_packages(),
15
+ install_requires=[],
16
+ classifiers=[
17
+ "Programming Language :: Python :: 3",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ ],
21
+ python_requires=">=3.8",
22
+ )
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: smartfleet-optimizer
3
+ Version: 0.1.0
4
+ Summary: Analytics library for fleet telemetry: risk scoring, alerts, maintenance prediction
5
+ Author: Satvik T M
6
+ Author-email: satvikw007@gmail.com
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: classifier
16
+ Dynamic: description
17
+ Dynamic: description-content-type
18
+ Dynamic: license-file
19
+ Dynamic: requires-python
20
+ Dynamic: summary
21
+
22
+ # fleet-optimization-engine-satvik25159712
23
+
24
+ Analytics library for fleet telemetry data. Provides risk scoring,
25
+ alert detection, fuel efficiency analysis and maintenance prediction.
26
+
27
+ ## Install
28
+ pip install fleet-optimization-engine-satvik25159712
29
+
30
+ ## Quick start
31
+ from fleet_optimization_pkg import TelemetryAnalyzer
32
+ analyzer = TelemetryAnalyzer()
33
+ profile = analyzer.build_risk_profile({
34
+ "vehicle_id": "VAN-001", "speed_kmh": 50,
35
+ "fuel_percent": 75, "engine_temp_c": 85
36
+ })
37
+ print(profile.risk_label)
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ fleet_optimization_pkg/__init__.py
5
+ fleet_optimization_pkg/analyzer.py
6
+ fleet_optimization_pkg/models.py
7
+ smartfleet_optimizer.egg-info/PKG-INFO
8
+ smartfleet_optimizer.egg-info/SOURCES.txt
9
+ smartfleet_optimizer.egg-info/dependency_links.txt
10
+ smartfleet_optimizer.egg-info/top_level.txt
11
+ tests/test_analyzer.py
@@ -0,0 +1 @@
1
+ fleet_optimization_pkg
@@ -0,0 +1,130 @@
1
+ """
2
+ test_analyzer.py
3
+ Unit tests for fleet_optimization_pkg.
4
+ """
5
+ import pytest
6
+ from fleet_optimization_pkg.analyzer import TelemetryAnalyzer
7
+ from fleet_optimization_pkg.models import AlertSeverity, VehicleRiskProfile
8
+
9
+
10
+ @pytest.fixture
11
+ def analyzer():
12
+ return TelemetryAnalyzer()
13
+
14
+ @pytest.fixture
15
+ def normal_reading():
16
+ return {"vehicle_id": "VAN-001", "speed_kmh": 50.0,
17
+ "fuel_percent": 75.0, "engine_temp_c": 85.0}
18
+
19
+ @pytest.fixture
20
+ def critical_reading():
21
+ return {"vehicle_id": "VAN-002", "speed_kmh": 112.0,
22
+ "fuel_percent": 5.0, "engine_temp_c": 115.0}
23
+
24
+
25
+ class TestRiskScore:
26
+
27
+ def test_normal_vehicle_scores_zero(self, analyzer, normal_reading):
28
+ assert analyzer.calculate_risk_score(normal_reading) == 0.0
29
+
30
+ def test_critical_vehicle_scores_high(self, analyzer, critical_reading):
31
+ assert analyzer.calculate_risk_score(critical_reading) >= 80.0
32
+
33
+ def test_score_is_between_0_and_100(self, analyzer, critical_reading):
34
+ score = analyzer.calculate_risk_score(critical_reading)
35
+ assert 0.0 <= score <= 100.0
36
+
37
+ def test_score_increases_with_engine_temp(self, analyzer):
38
+ low = {"vehicle_id": "X", "speed_kmh": 0,
39
+ "fuel_percent": 80, "engine_temp_c": 85}
40
+ high = {"vehicle_id": "X", "speed_kmh": 0,
41
+ "fuel_percent": 80, "engine_temp_c": 115}
42
+ assert analyzer.calculate_risk_score(high) > \
43
+ analyzer.calculate_risk_score(low)
44
+
45
+
46
+ class TestAlertDetection:
47
+
48
+ def test_no_alerts_for_normal_vehicle(self, analyzer, normal_reading):
49
+ assert analyzer.detect_alerts(normal_reading) == []
50
+
51
+ def test_critical_reading_generates_alerts(self, analyzer, critical_reading):
52
+ assert len(analyzer.detect_alerts(critical_reading)) >= 2
53
+
54
+ def test_high_temp_critical_alert(self, analyzer):
55
+ r = {"vehicle_id": "X", "speed_kmh": 50,
56
+ "fuel_percent": 60, "engine_temp_c": 115}
57
+ alerts = analyzer.detect_alerts(r)
58
+ assert any(a.alert_type == "HIGH_ENGINE_TEMP" and
59
+ a.severity == AlertSeverity.CRITICAL for a in alerts)
60
+
61
+ def test_low_fuel_warning_alert(self, analyzer):
62
+ r = {"vehicle_id": "X", "speed_kmh": 50,
63
+ "fuel_percent": 15.0, "engine_temp_c": 85}
64
+ alerts = analyzer.detect_alerts(r)
65
+ assert any(a.alert_type == "LOW_FUEL" for a in alerts)
66
+
67
+ def test_critical_fuel_alert(self, analyzer):
68
+ r = {"vehicle_id": "X", "speed_kmh": 50,
69
+ "fuel_percent": 5.0, "engine_temp_c": 85}
70
+ alerts = analyzer.detect_alerts(r)
71
+ assert any(a.severity == AlertSeverity.CRITICAL for a in alerts)
72
+
73
+ def test_speeding_alert(self, analyzer):
74
+ r = {"vehicle_id": "X", "speed_kmh": 112.0,
75
+ "fuel_percent": 60, "engine_temp_c": 85}
76
+ alerts = analyzer.detect_alerts(r)
77
+ assert any(a.alert_type == "SPEEDING" for a in alerts)
78
+
79
+
80
+ class TestFuelEfficiency:
81
+
82
+ def test_stationary_scores_100(self, analyzer):
83
+ r = {"vehicle_id": "X", "speed_kmh": 0,
84
+ "fuel_percent": 80, "engine_temp_c": 85}
85
+ assert analyzer.calculate_fuel_efficiency_score(r) == 100.0
86
+
87
+ def test_score_in_valid_range(self, analyzer, normal_reading):
88
+ score = analyzer.calculate_fuel_efficiency_score(normal_reading)
89
+ assert 0.0 <= score <= 100.0
90
+
91
+
92
+ class TestMaintenancePrediction:
93
+
94
+ def test_healthy_vehicle_no_maintenance(self, analyzer, normal_reading):
95
+ assert analyzer.predict_maintenance_needed(normal_reading) is False
96
+
97
+ def test_high_temp_low_fuel_needs_maintenance(self, analyzer):
98
+ r = {"vehicle_id": "X", "speed_kmh": 50,
99
+ "fuel_percent": 18.0, "engine_temp_c": 98.0}
100
+ assert analyzer.predict_maintenance_needed(r) is True
101
+
102
+
103
+ class TestSeverityClassification:
104
+
105
+ def test_empty_alerts_returns_info(self, analyzer):
106
+ assert analyzer.classify_alert_severity([]) == AlertSeverity.INFO
107
+
108
+ def test_critical_alerts_returns_critical(self, analyzer, critical_reading):
109
+ alerts = analyzer.detect_alerts(critical_reading)
110
+ assert analyzer.classify_alert_severity(alerts) == AlertSeverity.CRITICAL
111
+
112
+
113
+ class TestRiskProfile:
114
+
115
+ def test_returns_correct_type(self, analyzer, normal_reading):
116
+ assert isinstance(analyzer.build_risk_profile(normal_reading),
117
+ VehicleRiskProfile)
118
+
119
+ def test_normal_vehicle_is_low(self, analyzer, normal_reading):
120
+ assert analyzer.build_risk_profile(normal_reading).risk_label == "LOW"
121
+
122
+ def test_critical_vehicle_label(self, analyzer, critical_reading):
123
+ label = analyzer.build_risk_profile(critical_reading).risk_label
124
+ assert label in ("HIGH", "CRITICAL")
125
+
126
+ def test_to_dict_has_all_keys(self, analyzer, normal_reading):
127
+ d = analyzer.build_risk_profile(normal_reading).to_dict()
128
+ assert set(d.keys()) == {"vehicle_id", "risk_score", "risk_label",
129
+ "alerts", "fuel_efficiency_score",
130
+ "maintenance_due"}