Carregar ficheiros para "src/core"
This commit is contained in:
1
src/core/__init__.py
Normal file
1
src/core/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
|
||||
118
src/core/command.py
Normal file
118
src/core/command.py
Normal file
@ -0,0 +1,118 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List, Tuple, Any
|
||||
import numpy as np
|
||||
from .file_handler import MapData
|
||||
|
||||
class Command(ABC):
|
||||
@abstractmethod
|
||||
def execute(self) -> bool:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def undo(self) -> bool:
|
||||
pass
|
||||
|
||||
class MapValueCommand(Command):
|
||||
"""Command for single value changes in a map"""
|
||||
def __init__(self, map_data: MapData, x: int, y: int, new_value: float):
|
||||
self.map_data = map_data
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.new_value = new_value
|
||||
self.old_value = map_data.data[x, y]
|
||||
|
||||
def execute(self) -> bool:
|
||||
try:
|
||||
self.map_data.data[self.x, self.y] = self.new_value
|
||||
self.map_data.modified = True
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def undo(self) -> bool:
|
||||
try:
|
||||
self.map_data.data[self.x, self.y] = self.old_value
|
||||
self.map_data.modified = True
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
class RegionCommand(Command):
|
||||
"""Command for region modifications"""
|
||||
def __init__(self, map_data: MapData, x1: int, y1: int, x2: int, y2: int,
|
||||
new_values: np.ndarray):
|
||||
self.map_data = map_data
|
||||
self.x1 = x1
|
||||
self.y1 = y1
|
||||
self.x2 = x2
|
||||
self.y2 = y2
|
||||
self.new_values = new_values
|
||||
self.old_values = map_data.data[x1:x2+1, y1:y2+1].copy()
|
||||
|
||||
def execute(self) -> bool:
|
||||
try:
|
||||
self.map_data.data[self.x1:self.x2+1, self.y1:self.y2+1] = self.new_values
|
||||
self.map_data.modified = True
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def undo(self) -> bool:
|
||||
try:
|
||||
self.map_data.data[self.x1:self.x2+1, self.y1:self.y2+1] = self.old_values
|
||||
self.map_data.modified = True
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
class CommandHistory:
|
||||
def __init__(self, max_history: int = 50):
|
||||
self.max_history = max_history
|
||||
self.history: List[Command] = []
|
||||
self.current: int = -1
|
||||
|
||||
def execute(self, command: Command) -> bool:
|
||||
"""Execute a new command and add it to history"""
|
||||
if command.execute():
|
||||
# Remove any undone commands
|
||||
if self.current < len(self.history) - 1:
|
||||
self.history = self.history[:self.current + 1]
|
||||
|
||||
self.history.append(command)
|
||||
self.current += 1
|
||||
|
||||
# Limit history size
|
||||
if len(self.history) > self.max_history:
|
||||
self.history = self.history[-self.max_history:]
|
||||
self.current = len(self.history) - 1
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
def undo(self) -> bool:
|
||||
"""Undo the last command"""
|
||||
if self.can_undo():
|
||||
if self.history[self.current].undo():
|
||||
self.current -= 1
|
||||
return True
|
||||
return False
|
||||
|
||||
def redo(self) -> bool:
|
||||
"""Redo the last undone command"""
|
||||
if self.can_redo():
|
||||
self.current += 1
|
||||
return self.history[self.current].execute()
|
||||
return False
|
||||
|
||||
def can_undo(self) -> bool:
|
||||
"""Check if undo is possible"""
|
||||
return self.current >= 0
|
||||
|
||||
def can_redo(self) -> bool:
|
||||
"""Check if redo is possible"""
|
||||
return self.current < len(self.history) - 1
|
||||
|
||||
def clear(self):
|
||||
"""Clear command history"""
|
||||
self.history.clear()
|
||||
self.current = -1
|
||||
160
src/core/edc15_definitions.py
Normal file
160
src/core/edc15_definitions.py
Normal file
@ -0,0 +1,160 @@
|
||||
from typing import Dict, List
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class MapAxis:
|
||||
name: str
|
||||
values: List[float]
|
||||
units: str
|
||||
|
||||
@dataclass
|
||||
class EDC15MapInfo:
|
||||
name: str
|
||||
address: int
|
||||
rows: int
|
||||
cols: int
|
||||
value_type: str
|
||||
description: str
|
||||
x_axis: MapAxis
|
||||
y_axis: MapAxis
|
||||
units: str
|
||||
|
||||
# Common EDC15 map definitions
|
||||
EDC15_MAPS = {
|
||||
# Fuel Maps
|
||||
"MAIN_FUEL_MAP": EDC15MapInfo(
|
||||
name="Mapa Principal de Combustível",
|
||||
address=0x4000, # Example address
|
||||
rows=16,
|
||||
cols=16,
|
||||
value_type="float32",
|
||||
description="Mapa principal de injeção de combustível",
|
||||
x_axis=MapAxis("RPM", [800, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
|
||||
4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000],
|
||||
"rpm"),
|
||||
y_axis=MapAxis("Load", [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
|
||||
110, 120, 130, 140, 150],
|
||||
"%"),
|
||||
units="mg/stroke"
|
||||
),
|
||||
|
||||
"PILOT_INJECTION": EDC15MapInfo(
|
||||
name="Mapa de Pré-Injeção",
|
||||
address=0x4400, # Example address
|
||||
rows=12,
|
||||
cols=12,
|
||||
value_type="float32",
|
||||
description="Mapa de controle da pré-injeção",
|
||||
x_axis=MapAxis("RPM", [800, 1200, 1600, 2000, 2400, 2800, 3200, 3600,
|
||||
4000, 4400, 4800, 5200],
|
||||
"rpm"),
|
||||
y_axis=MapAxis("Load", [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165],
|
||||
"%"),
|
||||
units="mg/stroke"
|
||||
),
|
||||
|
||||
# Boost Maps
|
||||
"BOOST_CONTROL": EDC15MapInfo(
|
||||
name="Mapa de Controle de Boost",
|
||||
address=0x4800, # Example address
|
||||
rows=16,
|
||||
cols=12,
|
||||
value_type="float32",
|
||||
description="Mapa de controle de pressão do turbo",
|
||||
x_axis=MapAxis("RPM", [1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500,
|
||||
5000, 5500, 6000, 6500],
|
||||
"rpm"),
|
||||
y_axis=MapAxis("Load", [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
|
||||
110, 120, 130, 140, 150],
|
||||
"%"),
|
||||
units="mbar"
|
||||
),
|
||||
|
||||
# Timing Maps
|
||||
"INJECTION_TIMING": EDC15MapInfo(
|
||||
name="Mapa de Avanço de Injeção",
|
||||
address=0x4C00, # Example address
|
||||
rows=16,
|
||||
cols=16,
|
||||
value_type="float32",
|
||||
description="Mapa de avanço do ponto de injeção",
|
||||
x_axis=MapAxis("RPM", [800, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
|
||||
4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000],
|
||||
"rpm"),
|
||||
y_axis=MapAxis("Load", [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
|
||||
110, 120, 130, 140, 150],
|
||||
"%"),
|
||||
units="degrees"
|
||||
),
|
||||
|
||||
# EGR Maps
|
||||
"EGR_CONTROL": EDC15MapInfo(
|
||||
name="Mapa de Controle EGR",
|
||||
address=0x5000, # Example address
|
||||
rows=12,
|
||||
cols=12,
|
||||
value_type="float32",
|
||||
description="Mapa de controle da válvula EGR",
|
||||
x_axis=MapAxis("RPM", [800, 1200, 1600, 2000, 2400, 2800, 3200, 3600,
|
||||
4000, 4400, 4800, 5200],
|
||||
"rpm"),
|
||||
y_axis=MapAxis("Load", [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165],
|
||||
"%"),
|
||||
units="%"
|
||||
),
|
||||
|
||||
# Limit Maps
|
||||
"TORQUE_LIMIT": EDC15MapInfo(
|
||||
name="Mapa de Limite de Torque",
|
||||
address=0x5400, # Example address
|
||||
rows=12,
|
||||
cols=16,
|
||||
value_type="float32",
|
||||
description="Mapa de limite de torque do motor",
|
||||
x_axis=MapAxis("RPM", [800, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
|
||||
4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000],
|
||||
"rpm"),
|
||||
y_axis=MapAxis("Temperature", [0, 20, 40, 60, 70, 75, 80, 85, 90, 95,
|
||||
100, 105],
|
||||
"°C"),
|
||||
units="Nm"
|
||||
),
|
||||
}
|
||||
|
||||
# Checksum regions
|
||||
CHECKSUM_REGIONS = [
|
||||
(0x0000, 0x1000), # Example region 1
|
||||
(0x4000, 0x6000), # Example region 2
|
||||
]
|
||||
|
||||
# Known file signatures
|
||||
EDC15_SIGNATURES = {
|
||||
"EDC15P": bytes([0x55, 0xAA, 0x55, 0xAA]),
|
||||
"EDC15V": bytes([0xAA, 0x55, 0xAA, 0x55]),
|
||||
}
|
||||
|
||||
def calculate_checksum(data: bytes, start: int, end: int) -> int:
|
||||
"""Calculate checksum for a region of data"""
|
||||
checksum = 0
|
||||
for i in range(start, end):
|
||||
if i < len(data):
|
||||
checksum = (checksum + data[i]) & 0xFF
|
||||
return checksum
|
||||
|
||||
def validate_ecu_file(data: bytes) -> bool:
|
||||
"""Validate EDC15 file format and checksums"""
|
||||
if len(data) < 0x8000: # Minimum size check
|
||||
return False
|
||||
|
||||
# Check for known signatures
|
||||
for sig_name, signature in EDC15_SIGNATURES.items():
|
||||
if data.startswith(signature):
|
||||
# Verify checksums for each region
|
||||
for start, end in CHECKSUM_REGIONS:
|
||||
stored_checksum = data[end] if end < len(data) else 0
|
||||
calculated = calculate_checksum(data, start, end)
|
||||
if stored_checksum != calculated:
|
||||
return False
|
||||
return True
|
||||
|
||||
return False
|
||||
131
src/core/edc15_maps.py
Normal file
131
src/core/edc15_maps.py
Normal file
@ -0,0 +1,131 @@
|
||||
from typing import Dict, List, Tuple
|
||||
import numpy as np
|
||||
from .file_handler import MapData
|
||||
|
||||
class EDC15MapDefinition:
|
||||
def __init__(self, name: str, address: int, rows: int, cols: int,
|
||||
value_type: str, description: str = ""):
|
||||
self.name = name
|
||||
self.address = address
|
||||
self.rows = rows
|
||||
self.cols = cols
|
||||
self.value_type = value_type # 'uint8', 'uint16', 'float'
|
||||
self.description = description
|
||||
|
||||
class EDC15MapDetector:
|
||||
# Common EDC15 map signatures
|
||||
KNOWN_SIGNATURES = {
|
||||
b'\x00\x00\x80\x3F': 'float32', # 1.0f in IEEE 754
|
||||
b'\x00\x00\x00\x40': 'float32', # 2.0f in IEEE 754
|
||||
b'\xCD\xCC\xCC\x3D': 'float32', # 0.1f in IEEE 754
|
||||
}
|
||||
|
||||
# Common map sizes in EDC15
|
||||
COMMON_SIZES = [(8, 8), (16, 16), (12, 12), (16, 12), (12, 16)]
|
||||
|
||||
def __init__(self, data: bytes):
|
||||
self.data = data
|
||||
self.size = len(data)
|
||||
|
||||
def find_potential_maps(self) -> List[EDC15MapDefinition]:
|
||||
"""
|
||||
Find potential maps in the binary data based on known patterns
|
||||
"""
|
||||
potential_maps = []
|
||||
|
||||
# Search for known signatures
|
||||
for signature, value_type in self.KNOWN_SIGNATURES.items():
|
||||
offset = 0
|
||||
while True:
|
||||
offset = self.data.find(signature, offset)
|
||||
if offset == -1:
|
||||
break
|
||||
|
||||
# Check for potential map structure around signature
|
||||
for rows, cols in self.COMMON_SIZES:
|
||||
if self._validate_map_structure(offset, rows, cols, value_type):
|
||||
map_def = EDC15MapDefinition(
|
||||
f"Map_0x{offset:X}",
|
||||
offset,
|
||||
rows,
|
||||
cols,
|
||||
value_type
|
||||
)
|
||||
potential_maps.append(map_def)
|
||||
|
||||
offset += len(signature)
|
||||
|
||||
return potential_maps
|
||||
|
||||
def _validate_map_structure(self, offset: int, rows: int, cols: int,
|
||||
value_type: str) -> bool:
|
||||
"""
|
||||
Validate if a potential map structure exists at the given offset
|
||||
"""
|
||||
# Calculate required space for the map
|
||||
bytes_per_value = 4 if value_type == 'float32' else 2
|
||||
required_space = rows * cols * bytes_per_value
|
||||
|
||||
# Check if we have enough space in the file
|
||||
if offset + required_space > self.size:
|
||||
return False
|
||||
|
||||
# Validate data consistency
|
||||
try:
|
||||
data = self._extract_map_data(offset, rows, cols, value_type)
|
||||
|
||||
# Check for reasonable value ranges
|
||||
if value_type == 'float32':
|
||||
if not np.all(np.isfinite(data)):
|
||||
return False
|
||||
if np.any(np.abs(data) > 1000000): # Unreasonable values
|
||||
return False
|
||||
|
||||
# Check for patterns that suggest this is actually a map
|
||||
# 1. Check if values are somewhat continuous
|
||||
differences = np.abs(np.diff(data.ravel()))
|
||||
if np.max(differences) > 1000: # Too large jumps between values
|
||||
return False
|
||||
|
||||
# 2. Check if there's some variation (not all same value)
|
||||
if np.all(data == data[0, 0]):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def _extract_map_data(self, offset: int, rows: int, cols: int,
|
||||
value_type: str) -> np.ndarray:
|
||||
"""
|
||||
Extract map data from binary file
|
||||
"""
|
||||
bytes_per_value = 4 if value_type == 'float32' else 2
|
||||
total_bytes = rows * cols * bytes_per_value
|
||||
|
||||
raw_data = self.data[offset:offset + total_bytes]
|
||||
|
||||
if value_type == 'float32':
|
||||
data = np.frombuffer(raw_data, dtype=np.float32)
|
||||
else:
|
||||
data = np.frombuffer(raw_data, dtype=np.uint16)
|
||||
|
||||
return data.reshape((rows, cols))
|
||||
|
||||
def extract_map(self, map_def: EDC15MapDefinition) -> MapData:
|
||||
"""
|
||||
Extract map data based on map definition
|
||||
"""
|
||||
data = self._extract_map_data(
|
||||
map_def.address,
|
||||
map_def.rows,
|
||||
map_def.cols,
|
||||
map_def.value_type
|
||||
)
|
||||
|
||||
# Create axis data (placeholder - should be extracted from actual file)
|
||||
x_axis = np.linspace(0, map_def.cols - 1, map_def.cols)
|
||||
y_axis = np.linspace(0, map_def.rows - 1, map_def.rows)
|
||||
|
||||
return MapData(map_def.name, data, x_axis, y_axis)
|
||||
504
src/core/edc15p_maps.py
Normal file
504
src/core/edc15p_maps.py
Normal file
@ -0,0 +1,504 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
@dataclass
|
||||
class MapDefinition:
|
||||
name: str
|
||||
address: str # Hex address in the binary
|
||||
rows: int
|
||||
cols: int
|
||||
x_axis: List[float]
|
||||
y_axis: List[float]
|
||||
description: str
|
||||
units: str
|
||||
category: str
|
||||
group: str
|
||||
|
||||
# Map definitions for EDC15P
|
||||
EDC15P_MAPS = {
|
||||
# Drivers Wish [FUEL]
|
||||
"drivers_wish_1": MapDefinition(
|
||||
name="Drivers Wish Map 1",
|
||||
address="04D206",
|
||||
rows=12,
|
||||
cols=8,
|
||||
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
|
||||
description="Drivers Wish Map 1",
|
||||
units="FUEL",
|
||||
category="Fuel",
|
||||
group="Drivers Wish [FUEL]"
|
||||
),
|
||||
"drivers_wish_2": MapDefinition(
|
||||
name="Drivers Wish Map 2",
|
||||
address="06D206",
|
||||
rows=12,
|
||||
cols=8,
|
||||
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
|
||||
description="Drivers Wish Map 2",
|
||||
units="FUEL",
|
||||
category="Fuel",
|
||||
group="Drivers Wish [FUEL]"
|
||||
),
|
||||
|
||||
# Torque [FUEL]
|
||||
"torque_1": MapDefinition(
|
||||
name="Torque Map 1",
|
||||
address="04D8D2",
|
||||
rows=3,
|
||||
cols=20,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95], # Load %
|
||||
description="Torque Control Map 1",
|
||||
units="FUEL",
|
||||
category="Torque",
|
||||
group="Torque [FUEL]"
|
||||
),
|
||||
"torque_2": MapDefinition(
|
||||
name="Torque Map 2",
|
||||
address="06D8D2",
|
||||
rows=3,
|
||||
cols=20,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95], # Load %
|
||||
description="Torque Control Map 2",
|
||||
units="FUEL",
|
||||
category="Torque",
|
||||
group="Torque [FUEL]"
|
||||
),
|
||||
|
||||
# Smoke Limiter [FUEL]
|
||||
"smoke_limiter_1": MapDefinition(
|
||||
name="Smoke Limiter Map 1",
|
||||
address="04DA04",
|
||||
rows=16,
|
||||
cols=13,
|
||||
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
|
||||
description="Smoke Limiter Map 1",
|
||||
units="FUEL",
|
||||
category="Limiters",
|
||||
group="Smoke Limiter [FUEL]"
|
||||
),
|
||||
"smoke_limiter_2": MapDefinition(
|
||||
name="Smoke Limiter Map 2",
|
||||
address="04DBF6",
|
||||
rows=16,
|
||||
cols=13,
|
||||
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
|
||||
description="Smoke Limiter Map 2",
|
||||
units="FUEL",
|
||||
category="Limiters",
|
||||
group="Smoke Limiter [FUEL]"
|
||||
),
|
||||
"smoke_limiter_3": MapDefinition(
|
||||
name="Smoke Limiter Map 3",
|
||||
address="06DA04",
|
||||
rows=16,
|
||||
cols=13,
|
||||
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
|
||||
description="Smoke Limiter Map 3",
|
||||
units="FUEL",
|
||||
category="Limiters",
|
||||
group="Smoke Limiter [FUEL]"
|
||||
),
|
||||
"smoke_limiter_4": MapDefinition(
|
||||
name="Smoke Limiter Map 4",
|
||||
address="06DBF6",
|
||||
rows=16,
|
||||
cols=13,
|
||||
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
|
||||
description="Smoke Limiter Map 4",
|
||||
units="FUEL",
|
||||
category="Limiters",
|
||||
group="Smoke Limiter [FUEL]"
|
||||
),
|
||||
|
||||
# Speed Limiter Via Temp [ENGINE LOAD]
|
||||
"speed_temp_limiter_1": MapDefinition(
|
||||
name="Speed Temperature Limiter 1",
|
||||
address="04E732",
|
||||
rows=4,
|
||||
cols=4,
|
||||
x_axis=[0, 30, 60, 90], # Temperature
|
||||
y_axis=[0, 25, 50, 75], # Speed %
|
||||
description="Speed Limiter via Temperature Map 1",
|
||||
units="ENGINE LOAD",
|
||||
category="Limiters",
|
||||
group="Speed Limiter Via Temp [ENGINE LOAD]"
|
||||
),
|
||||
"speed_temp_limiter_2": MapDefinition(
|
||||
name="Speed Temperature Limiter 2",
|
||||
address="06E732",
|
||||
rows=4,
|
||||
cols=4,
|
||||
x_axis=[0, 30, 60, 90], # Temperature
|
||||
y_axis=[0, 25, 50, 75], # Speed %
|
||||
description="Speed Limiter via Temperature Map 2",
|
||||
units="ENGINE LOAD",
|
||||
category="Limiters",
|
||||
group="Speed Limiter Via Temp [ENGINE LOAD]"
|
||||
),
|
||||
|
||||
# Injection Limiter Via Temp [LOAD]
|
||||
"injection_temp_limiter_1": MapDefinition(
|
||||
name="Injection Temperature Limiter 1",
|
||||
address="04F238",
|
||||
rows=3,
|
||||
cols=3,
|
||||
x_axis=[0, 50, 100], # Temperature
|
||||
y_axis=[0, 50, 100], # Load %
|
||||
description="Injection Limiter via Temperature Map 1",
|
||||
units="LOAD",
|
||||
category="Limiters",
|
||||
group="Injection Limiter Via Temp [LOAD]"
|
||||
),
|
||||
"injection_temp_limiter_2": MapDefinition(
|
||||
name="Injection Temperature Limiter 2",
|
||||
address="06F238",
|
||||
rows=3,
|
||||
cols=3,
|
||||
x_axis=[0, 50, 100], # Temperature
|
||||
y_axis=[0, 50, 100], # Load %
|
||||
description="Injection Limiter via Temperature Map 2",
|
||||
units="LOAD",
|
||||
category="Limiters",
|
||||
group="Injection Limiter Via Temp [LOAD]"
|
||||
),
|
||||
|
||||
# Boost Limiter Via Temperature [mBAR]
|
||||
"boost_temp_limiter_1": MapDefinition(
|
||||
name="Boost Temperature Limiter 1",
|
||||
address="051FA0",
|
||||
rows=16,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300], # Temperature
|
||||
description="Boost Limiter via Temperature Map 1",
|
||||
units="mBAR",
|
||||
category="Limiters",
|
||||
group="Boost Limiter Via Temperature [mBAR]"
|
||||
),
|
||||
"boost_temp_limiter_2": MapDefinition(
|
||||
name="Boost Temperature Limiter 2",
|
||||
address="071FA0",
|
||||
rows=16,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300], # Temperature
|
||||
description="Boost Limiter via Temperature Map 2",
|
||||
units="mBAR",
|
||||
category="Limiters",
|
||||
group="Boost Limiter Via Temperature [mBAR]"
|
||||
),
|
||||
|
||||
# Spraying Time [DEG]
|
||||
"spraying_time_1": MapDefinition(
|
||||
name="Spraying Time Map 1",
|
||||
address="054548",
|
||||
rows=10,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90], # Load %
|
||||
description="Spraying Time Map 1",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_2": MapDefinition(
|
||||
name="Spraying Time Map 2",
|
||||
address="05465C",
|
||||
rows=15,
|
||||
cols=19,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
|
||||
description="Spraying Time Map 2",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_3": MapDefinition(
|
||||
name="Spraying Time Map 3",
|
||||
address="0548E2",
|
||||
rows=15,
|
||||
cols=19,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
|
||||
description="Spraying Time Map 3",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_4": MapDefinition(
|
||||
name="Spraying Time Map 4",
|
||||
address="054B68",
|
||||
rows=15,
|
||||
cols=19,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
|
||||
description="Spraying Time Map 4",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_5": MapDefinition(
|
||||
name="Spraying Time Map 5",
|
||||
address="074548",
|
||||
rows=10,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90], # Load %
|
||||
description="Spraying Time Map 5",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_6": MapDefinition(
|
||||
name="Spraying Time Map 6",
|
||||
address="07465C",
|
||||
rows=15,
|
||||
cols=19,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
|
||||
description="Spraying Time Map 6",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_7": MapDefinition(
|
||||
name="Spraying Time Map 7",
|
||||
address="0748E2",
|
||||
rows=15,
|
||||
cols=19,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
|
||||
description="Spraying Time Map 7",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
"spraying_time_8": MapDefinition(
|
||||
name="Spraying Time Map 8",
|
||||
address="074B68",
|
||||
rows=15,
|
||||
cols=19,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
|
||||
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
|
||||
description="Spraying Time Map 8",
|
||||
units="DEG",
|
||||
category="Timing",
|
||||
group="Spraying Time [DEG]"
|
||||
),
|
||||
|
||||
# Air Mass Substitutive value [FUEL]
|
||||
"air_mass_sub_1": MapDefinition(
|
||||
name="Air Mass Substitutive Value 1",
|
||||
address="055632",
|
||||
rows=8,
|
||||
cols=8,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
|
||||
description="Air Mass Substitutive Value Map 1",
|
||||
units="FUEL",
|
||||
category="Air Mass",
|
||||
group="Air Mass Substitutive value [FUEL]"
|
||||
),
|
||||
"air_mass_sub_2": MapDefinition(
|
||||
name="Air Mass Substitutive Value 2",
|
||||
address="075632",
|
||||
rows=8,
|
||||
cols=8,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
|
||||
description="Air Mass Substitutive Value Map 2",
|
||||
units="FUEL",
|
||||
category="Air Mass",
|
||||
group="Air Mass Substitutive value [FUEL]"
|
||||
),
|
||||
|
||||
# Boost Pressure [mBAR]
|
||||
"boost_pressure_1": MapDefinition(
|
||||
name="Boost Pressure Map 1",
|
||||
address="056926",
|
||||
rows=16,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
|
||||
description="Boost Pressure Control Map 1",
|
||||
units="mBAR",
|
||||
category="Boost",
|
||||
group="Boost Pressure [mBAR]"
|
||||
),
|
||||
"boost_pressure_2": MapDefinition(
|
||||
name="Boost Pressure Map 2",
|
||||
address="076926",
|
||||
rows=16,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
|
||||
description="Boost Pressure Control Map 2",
|
||||
units="mBAR",
|
||||
category="Boost",
|
||||
group="Boost Pressure [mBAR]"
|
||||
),
|
||||
|
||||
# Boost Limiter Via Patm [mBAR]
|
||||
"boost_patm_limiter_1": MapDefinition(
|
||||
name="Boost Patm Limiter 1",
|
||||
address="056F1C",
|
||||
rows=10,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250], # Atmospheric Pressure
|
||||
description="Boost Limiter via Atmospheric Pressure Map 1",
|
||||
units="mBAR",
|
||||
category="Limiters",
|
||||
group="Boost Limiter Via Patm [mBAR]"
|
||||
),
|
||||
"boost_patm_limiter_2": MapDefinition(
|
||||
name="Boost Patm Limiter 2",
|
||||
address="076F1C",
|
||||
rows=10,
|
||||
cols=10,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
|
||||
y_axis=[800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250], # Atmospheric Pressure
|
||||
description="Boost Limiter via Atmospheric Pressure Map 2",
|
||||
units="mBAR",
|
||||
category="Limiters",
|
||||
group="Boost Limiter Via Patm [mBAR]"
|
||||
),
|
||||
|
||||
# Advance Limiter Via Temp [DEG]
|
||||
"advance_temp_limiter_1": MapDefinition(
|
||||
name="Advance Temperature Limiter 1",
|
||||
address="0581B6",
|
||||
rows=14,
|
||||
cols=11,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130], # Temperature
|
||||
description="Advance Limiter via Temperature Map 1",
|
||||
units="DEG",
|
||||
category="Limiters",
|
||||
group="Advance Limiter Via Temp [DEG]"
|
||||
),
|
||||
"advance_temp_limiter_2": MapDefinition(
|
||||
name="Advance Temperature Limiter 2",
|
||||
address="0781B6",
|
||||
rows=14,
|
||||
cols=11,
|
||||
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000], # RPM
|
||||
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130], # Temperature
|
||||
description="Advance Limiter via Temperature Map 2",
|
||||
units="DEG",
|
||||
category="Limiters",
|
||||
group="Advance Limiter Via Temp [DEG]"
|
||||
),
|
||||
|
||||
# Idle Speed [RPM]
|
||||
"idle_speed_1": MapDefinition(
|
||||
name="Idle Speed Control 1",
|
||||
address="056FEC",
|
||||
rows=1,
|
||||
cols=2,
|
||||
x_axis=[0], # No X axis (single column)
|
||||
y_axis=[0, 1], # Two states
|
||||
description="Idle Speed Control Map 1",
|
||||
units="RPM",
|
||||
category="Speed",
|
||||
group="Idle Speed [RPM]"
|
||||
),
|
||||
|
||||
# Maximum Boost Pressure [mBAR]
|
||||
"max_boost_pressure_1": MapDefinition(
|
||||
name="Maximum Boost Pressure 1",
|
||||
address="051C84",
|
||||
rows=1,
|
||||
cols=1,
|
||||
x_axis=[0], # Single value
|
||||
y_axis=[0], # Single value
|
||||
description="Maximum Boost Pressure Map 1",
|
||||
units="mBAR",
|
||||
category="Limiters",
|
||||
group="Maximum Boost Pressure [mBAR]"
|
||||
),
|
||||
"max_boost_pressure_2": MapDefinition(
|
||||
name="Maximum Boost Pressure 2",
|
||||
address="071C84",
|
||||
rows=1,
|
||||
cols=1,
|
||||
x_axis=[0], # Single value
|
||||
y_axis=[0], # Single value
|
||||
description="Maximum Boost Pressure Map 2",
|
||||
units="mBAR",
|
||||
category="Limiters",
|
||||
group="Maximum Boost Pressure [mBAR]"
|
||||
),
|
||||
|
||||
# Maximum RPM Limiter [RPM]
|
||||
"max_rpm_limiter_1": MapDefinition(
|
||||
name="Maximum RPM Limiter 1",
|
||||
address="0541A3",
|
||||
rows=1,
|
||||
cols=1,
|
||||
x_axis=[0], # Single value
|
||||
y_axis=[0], # Single value
|
||||
description="Maximum RPM Limiter Map 1",
|
||||
units="RPM",
|
||||
category="Limiters",
|
||||
group="Maximum RPM Limiter [RPM]"
|
||||
),
|
||||
"max_rpm_limiter_2": MapDefinition(
|
||||
name="Maximum RPM Limiter 2",
|
||||
address="0741A3",
|
||||
rows=1,
|
||||
cols=1,
|
||||
x_axis=[0], # Single value
|
||||
y_axis=[0], # Single value
|
||||
description="Maximum RPM Limiter Map 2",
|
||||
units="RPM",
|
||||
category="Limiters",
|
||||
group="Maximum RPM Limiter [RPM]"
|
||||
)
|
||||
}
|
||||
|
||||
def get_map_definition(map_id: str) -> Optional[MapDefinition]:
|
||||
"""Get map definition by ID"""
|
||||
return EDC15P_MAPS.get(map_id)
|
||||
|
||||
def list_maps() -> List[str]:
|
||||
"""List all available map IDs"""
|
||||
return list(EDC15P_MAPS.keys())
|
||||
|
||||
def list_maps_by_group() -> Dict[str, List[MapDefinition]]:
|
||||
"""List maps grouped by their groups"""
|
||||
groups: Dict[str, List[MapDefinition]] = {}
|
||||
|
||||
# First pass: collect all unique groups
|
||||
for map_def in EDC15P_MAPS.values():
|
||||
if map_def.group not in groups:
|
||||
groups[map_def.group] = []
|
||||
|
||||
# Second pass: add maps to their groups
|
||||
for map_id, map_def in EDC15P_MAPS.items():
|
||||
groups[map_def.group].append(map_def)
|
||||
|
||||
return groups
|
||||
|
||||
def list_maps_by_category() -> Dict[str, List[MapDefinition]]:
|
||||
"""List maps grouped by category"""
|
||||
categories: Dict[str, List[MapDefinition]] = {}
|
||||
|
||||
# First pass: collect all unique categories
|
||||
for map_def in EDC15P_MAPS.values():
|
||||
if map_def.category not in categories:
|
||||
categories[map_def.category] = []
|
||||
|
||||
# Second pass: add maps to their categories
|
||||
for map_id, map_def in EDC15P_MAPS.items():
|
||||
categories[map_def.category].append(map_def)
|
||||
|
||||
return categories
|
||||
Reference in New Issue
Block a user