import React, { useContext, useState } from "react"; import { logger } from "../../services/monitoring"; import api from "../../services/vehiclesAPI"; import { validateVIN } from "../../utils/validationSupplier"; const VehicleContext = React.createContext(); export const VehicleConsumer = VehicleContext.Consumer; const validateAdd = (vehicle) => { if (vehicle == null) { throw new Error("No vehicle data"); } if (!vehicle.vin || vehicle.vin.length === 0) { throw new Error("VIN required"); } if (vehicle.vin.length > 17) { throw new Error("VIN cannot be larger than 17 characters"); } }; export const VehicleProvider = ({ children }) => { const [busy, setBusy] = useState(false); const [vehicle, setVehicle] = useState({}); const [vehicles, setVehicles] = useState([]); const [totalVehicles, setTotalVehicles] = useState(0); const [fleets, setFleets] = useState([]); const [totalFleets, setTotalFleets] = useState(0); const [models, setModels] = useState([]); const [years, setYears] = useState([]); const [flashpacks, setFlashpacks] = useState([]); const [totalFlashpacks, setTotalFlashpacks] = useState(0); const [flashpackECUMappings, setFlashpackECUMappings] = useState([]) const [totalFlashpackECUMappings, setTotalFlashpackECUMappings] = useState(0) const addConnections = async (cars, token) => { try { if (cars.length === 0) return; const vins = cars.map((car) => car.vin); const result = await api.getConnections({ "VINs": vins }, token); if (result.error) { throw new Error(`Add connections error. ${result.message}`); } cars.forEach((car) => { car.connected = result[car.vin] || false; car.connectedHMI = result[`2:${car.vin}`] || false; }); } catch (e) { logger.error(e.stack); } }; const addVehicle = async (v, token) => { try { setBusy(true); validateAdd(v); const result = await api.addVehicle(v, token); if (result.error) throw new Error(`Add vehicle error. ${result.message}`); return result; } finally { setBusy(false); } }; const addTags = async (vins, tags, token) => { try { setBusy(true); vins.forEach(vin => validateVIN(vin)); const validateTags = tags.every(tag => typeof tag === "string"); if (!validateTags) throw new Error("Invalid Tag"); const result = await api.addTags(vins, tags, token) if (result.error) throw new Error(`Add tags error. ${result.message}`); } finally { setBusy(false) } } const getConnections = async (vins, token) => { try { setBusy(true); const result = await api.getConnections({ "VINs": vins }, token); if (result.error) throw new Error(`Get connections error. ${result.message}`); return result; } finally { setBusy(false); } }; const getECUs = async (search, token) => { try { setBusy(true); const result = await api.getECUs(search, token); if (result.error) throw new Error(`Get ECUs error. ${result.message}`); return result; } finally { setBusy(false); } }; const getLocations = async (token) => { try { setBusy(true); const result = await api.getLocations(token); if (result.error) throw new Error(`Get locations error. ${result.message}`); return result; } finally { setBusy(false); } }; const getLocationsVehiclePaths = async (token, param, vins) => { try { setBusy(true); const result = await api.getLocationsVehiclePaths(token, param, vins); if (result.error) throw new Error(`Get locations vehicle paths error. ${result.message}`); return result; } finally { setBusy(false); } }; const getModels = async (token) => { try { setBusy(true); const result = await api.getModels(token); if (result.error) throw new Error(`Get models error. ${result.message}`); setModels(result.data); } finally { setBusy(false); } }; const getState = async (token, vin) => { try { setBusy(true); const result = await api.getState(token, vin); if (result.error) throw new Error(`Get state error. ${result.message}`); return result; } finally { setBusy(false); } }; const getVehicle = async (vin, token) => { try { setBusy(true); validateVIN(vin); const result = await api.getVehicle(vin, token); if (result.error) throw new Error(`Get vehicle error. ${result.message}`); setVehicle(result ?? []); return result; } finally { setBusy(false); } }; const getVehicles = async (search, token) => { try { setBusy(true); const result = await api.getVehicles(search, token); if (result.error) { setVehicles([]); throw new Error(`Get vehicles error. ${result.message}`); } await addConnections(result.data, token); setVehicles(result.data ?? []); if (result.total) { setTotalVehicles(result.total); } } finally { setBusy(false); } }; const getYears = async (token) => { try { setBusy(true); const result = await api.getYears(token); if (result.error) throw new Error(`Get years error. ${result.message}`); setYears(result.data); } finally { setBusy(false); } }; const sendCommand = async (vins, command, token) => { try { setBusy(true); const result = await api.sendCommand(vins, command, token); if (result.error) throw new Error(`Send command error. ${result.message}`); return result; } finally { setBusy(false); } }; const sendDiagnosticCommand = async (vins, command, token) => { try { setBusy(true); const result = await api.sendDiagnosticCommand(vins, command, token); if (result.error) throw new Error(`Send diagnostic command error. ${result.message}`); return result; } finally { setBusy(false); } }; const updateVehicle = async (vin, v, token) => { try { setBusy(true); validateVIN(vin); validateVehicle(v); const result = await api.updateVehicle(vin, v, token); if (result.error) throw new Error(`Update vehicle error. ${result.message}`); return result; } finally { setBusy(false); } }; const uploadConfig = async (vin, forced, token) => { try { setBusy(true); validateVIN(vin); const result = await api.updateConfig(vin, forced, token); if (result.error) throw new Error(`Update vehicle error. ${result.message}`); return result; } finally { setBusy(false); } } const getCANSignals = async (vin, token) => { try { setBusy(true); validateVIN(vin); const result = await api.getCANSignals(vin, token); if (result.error) throw new Error(`Get CAN signals error. ${result.message}`); return result; } finally { setBusy(false); } }; const getFleets = async (vin, search, token) => { try { setBusy(true); validateVIN(vin); const result = await api.getFleets(vin, search, token); if (result.error) { setFleets([]); throw new Error(`Get Fleets of vehicle`) } setFleets(result.data ?? []); if (result.total) { setTotalFleets(result.total); } } finally { setBusy(false) } } const getVersionLog = async (search, token) => { try { setBusy(true); const result = await api.getVersionLog(search, token); if (result.error) throw new Error(`Get version log error. ${result.message}`); return result; } finally { setBusy(false); } }; const getAllFlashpacks = async (model, trim, year, options, token) => { try { setBusy(true); const result = await api.getAllFlashpacks(model, trim, year, options, token); if (result.error) { throw new Error(`Get all flashpacks error. ${result.message}`); } setFlashpacks(result.data); if (options && options.offset === 0 && result.total) { setTotalFlashpacks(result.total); } return result; } finally { setBusy(false); } }; const getFlashpackECUMappings = async (model, trim, year, flashpack, options, token) => { try { setBusy(true); const result = await api.getFlashpackECUMappings(model, trim, year, flashpack, options, token); if (result.error) { throw new Error(`Get flashpack ecu mappings error. ${result.message}`); } setFlashpackECUMappings(result.data); if (options && options.offset === 0 && result.total) { setTotalFlashpackECUMappings(result.total); } return result; } finally { setBusy(false); } }; const addFlashpackVersion = async (model, trim, year, flashpack, carFlashpackVersions, token) => { try { setBusy(true); const data = { "car_model": model, "car_trim": trim, "car_year": year, "flashpack": flashpack, "ecu_versions": carFlashpackVersions, } const result = await api.addFlashpackVersion(data, token) if (result.error) { throw new Error(`Add flashpack version error. ${result.message}`); } return result; } finally { setBusy(false) } } const addFlashpackVersionECUMapping = async (model, trim, year, flashpack, ecuName, ecuVersion, token) => { try { setBusy(true); const data = { "car_ecu_name": ecuName, "car_ecu_version": ecuVersion, } const result = await api.addFlashpackVersionECUMapping(model, trim, year, flashpack, data, token) if (result.error) { throw new Error(`Add flashpack version ECU mapping error. ${result.message}`); } return result; } finally { setBusy(false) } } const deleteFlashpackVersion = async (model, trim, year, flashpack, token) => { try { setBusy(true); const data = { "car_model": model, "car_trim": trim, "car_year": year, "flashpack": flashpack, } const result = await api.deleteFlashpackVersion(data, token); if (result.error) { throw new Error(`Delete flashpack version error. ${result.message}`); } return result; } finally { setBusy(false); } }; const deleteFlashpackVersionECUMapping = async (model, trim, year, flashpack, ecuName, ecuVersion, token) => { try { setBusy(true); const result = await api.deleteFlashpackVersionECUMapping(model, trim, year, flashpack, ecuName, ecuVersion, token); if (result.error) { throw new Error(`Delete flashpack ecu mapping error. ${result.message}`); } return result; } finally { setBusy(false); } }; const getCarFlashpackVersionInfo = async (vin, token) => { try { setBusy(true); const result = await api.getCarFlashpackVersionInfo(vin, token); if (result.error) { throw new Error(`Get car flashpack version info error. ${result.message}`); } return result; } finally { setBusy(false); } } return ( {children} ); }; const validateVehicle = (v) => { if (v == null) { throw new Error("No vehicle data"); } validateVIN(v.vin); }; export const useVehicleContext = () => useContext(VehicleContext);