UNPKG

react-native-obd-retriver

Version:

A React Native hook library to manage Bluetooth Low Energy connections and communication with ELM327 OBD-II adapters.

2 lines 28.8 kB
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.BaseDTCRetriever=void 0;var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));var _logger=require("../../utils/logger");var _constants=require("../utils/constants");var _helpers=require("../utils/helpers");var BaseDTCRetriever=exports.BaseDTCRetriever=function(){function BaseDTCRetriever(sendCommand,mode){(0,_classCallCheck2.default)(this,BaseDTCRetriever);this.isCan=false;this.protocolNumber=0;this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.UNKNOWN;this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.UNKNOWN;this.ecuAddress=null;this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.INITIALIZED;this.isHeaderEnabled=false;this.isEchoEnabled=false;this.lineFeedsDisabled=false;this.spacesDisabled=false;this.sendCommand=sendCommand;this.mode=mode;this.responsePrefix=(parseInt(mode,16)+0x40).toString(16).toUpperCase();}return(0,_createClass2.default)(BaseDTCRetriever,[{key:"delay",value:function delay(ms){return new Promise(function(resolve){setTimeout(resolve,ms);});}},{key:"configureAdapter",value:(function(){var _configureAdapter=(0,_asyncToGenerator2.default)(function*(){yield _logger.log.info(`[${this.constructor.name}] Configuring adapter for DTC retrieval (Mode ${this.mode})`);try{yield this.sendCommand(_constants.ELM_COMMANDS.RESET);yield this.delay(_constants.DELAYS_MS.RESET);}catch(error){yield _logger.log.warn(`[${this.constructor.name}] Reset warning:`,{error:error instanceof Error?error.message:String(error)});}var setupCommands=[{cmd:_constants.ELM_COMMANDS.ECHO_OFF,desc:'Disable echo'},{cmd:_constants.ELM_COMMANDS.LINEFEEDS_OFF,desc:'Disable linefeeds'},{cmd:_constants.ELM_COMMANDS.SPACES_OFF,desc:'Disable spaces'},{cmd:_constants.ELM_COMMANDS.HEADERS_ON,desc:'Enable headers'},{cmd:_constants.ELM_COMMANDS.ADAPTIVE_TIMING_1,desc:'Set adaptive timing mode 1'}];for(var _ref of setupCommands){var cmd=_ref.cmd;var desc=_ref.desc;yield _logger.log.debug(`[${this.constructor.name}] Setup: ${desc}`);try{var response=yield this.sendCommand(cmd,2000);if(cmd===_constants.ELM_COMMANDS.ECHO_OFF)this.isEchoEnabled=false;else if(cmd===_constants.ELM_COMMANDS.LINEFEEDS_OFF)this.lineFeedsDisabled=true;else if(cmd===_constants.ELM_COMMANDS.SPACES_OFF)this.spacesDisabled=true;else if(cmd===_constants.ELM_COMMANDS.HEADERS_ON)this.isHeaderEnabled=true;if(response&&!(0,_helpers.isResponseOk)(response)&&!this.isErrorResponse(response)&&response.trim()!=='?'){yield _logger.log.warn(`[${this.constructor.name}] Unexpected response for ${cmd}: ${response}`);}else if((response==null?void 0:response.trim())==='?'){yield _logger.log.warn(`[${this.constructor.name}] Command "${cmd}" returned '?', possibly unsupported but continuing.`);}}catch(error){yield _logger.log.error(`[${this.constructor.name}] Error during setup command ${cmd}:`,{error:error instanceof Error?error.message:String(error)});}yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);}this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.CONFIGURING;yield this.detectProtocol();yield this.configureForProtocol();if(!this.shouldKeepHeadersEnabled()){try{yield _logger.log.debug(`[${this.constructor.name}] Disabling headers for cleaner responses (ATH0)`);yield this.sendCommand(_constants.ELM_COMMANDS.HEADERS_OFF,2000);this.isHeaderEnabled=false;}catch(error){yield _logger.log.warn(`[${this.constructor.name}] Failed to disable headers (ATH0)`,{error:error instanceof Error?error.message:String(error)});}}this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.READY;yield _logger.log.info(`[${this.constructor.name}] Adapter configuration complete. Protocol: ${this.protocolType} (${this.protocolNumber}), isCAN: ${this.isCan}, Headers: ${this.isHeaderEnabled}`);});function configureAdapter(){return _configureAdapter.apply(this,arguments);}return configureAdapter;}())},{key:"configureForProtocol",value:(function(){var _configureForProtocol=(0,_asyncToGenerator2.default)(function*(){yield _logger.log.debug(`[${this.constructor.name}] Applying config for protocol: ${this.protocolType}`);if(this.isCan){try{yield _logger.log.debug(`[${this.constructor.name}] Enabling CAN Auto Formatting (ATCAF1)`);yield this.sendCommand(_constants.ELM_COMMANDS.CAN_AUTO_FORMAT_ON,2000);}catch(error){yield _logger.log.warn(`[${this.constructor.name}] Failed to enable CAN Auto Formatting`,{error:error instanceof Error?error.message:String(error)});}yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);var flowControlHeader=this.headerFormat===BaseDTCRetriever.HEADER_FORMATS.CAN_11BIT?'7E0':'18DA10F1';var flowControlData='300000';var flowControlMode='1';yield _logger.log.debug(`[${this.constructor.name}] Setting default CAN flow control: Header=${flowControlHeader}, Data=${flowControlData}, Mode=${flowControlMode}`);try{yield this.sendCommand(`ATFCSH${flowControlHeader}`,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);yield this.sendCommand(`ATFCSD${flowControlData}`,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);yield this.sendCommand(`ATFCSM${flowControlMode}`,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);}catch(error){yield _logger.log.warn(`[${this.constructor.name}] Default CAN flow control setup warning:`,{error:error instanceof Error?error.message:String(error)});}}else if(this.protocolType===BaseDTCRetriever.PROTOCOL_TYPES.KWP){try{yield _logger.log.debug(`[${this.constructor.name}] Setting KWP timing (ATAT2)`);yield this.sendCommand(_constants.ELM_COMMANDS.ADAPTIVE_TIMING_2,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);}catch(error){yield _logger.log.warn(`[${this.constructor.name}] KWP timing (ATAT2) warning:`,{error:error instanceof Error?error.message:String(error)});}}else{yield _logger.log.debug(`[${this.constructor.name}] No specific configuration needed for protocol ${this.protocolType}`);}});function configureForProtocol(){return _configureForProtocol.apply(this,arguments);}return configureForProtocol;}())},{key:"shouldKeepHeadersEnabled",value:function shouldKeepHeadersEnabled(){if(this.isCan||this.protocolType===BaseDTCRetriever.PROTOCOL_TYPES.UNKNOWN){return true;}return false;}},{key:"isErrorResponse",value:function isErrorResponse(response){return(0,_helpers.isResponseError)(response);}},{key:"extractEcuAddress",value:function extractEcuAddress(line){if(!line)return null;var trimmedLine=line.trim().toUpperCase();var addresses=(0,_helpers.extractEcuAddresses)(trimmedLine);var firstAddress=addresses.length>0?addresses[0]:null;return firstAddress!==undefined?firstAddress:null;}},{key:"createEmptyResponse",value:function createEmptyResponse(){var _this$ecuAddress;return{rawString:null,rawResponse:null,response:null,rawBytesResponseFromSendCommand:[],isCan:this.isCan,protocolNumber:this.protocolNumber,ecuAddress:(_this$ecuAddress=this.ecuAddress)!=null?_this$ecuAddress:undefined};}},{key:"retrieveRawDTCs",value:(function(){var _retrieveRawDTCs=(0,_asyncToGenerator2.default)(function*(){var maxRetries=3;var retryCount=0;yield _logger.log.debug(`[${this.constructor.name}] Starting Mode ${this.mode} retrieval...`);yield this.configureAdapter();if(this.protocolState===BaseDTCRetriever.PROTOCOL_STATES.ERROR){yield _logger.log.error(`[${this.constructor.name}] Adapter configuration failed. Aborting DTC retrieval.`);return null;}while(retryCount<maxRetries){try{var _result$rawString,_result$response,_result$response$,_result$response2,_this$ecuAddress2;yield _logger.log.debug(`[${this.constructor.name}] Attempt ${retryCount+1}/${maxRetries}`);var result=yield this.verifyAndGetResponse();if(result===null){yield _logger.log.warn(`[${this.constructor.name}] No valid response or critical error during attempt ${retryCount+1}.`);retryCount++;if(retryCount<maxRetries){yield _logger.log.debug(`[${this.constructor.name}] Retrying after delay...`);yield this.delay(_constants.DELAYS_MS.RETRY);}continue;}var hasNoData=(_result$rawString=result.rawString)==null?void 0:_result$rawString.toUpperCase().includes(_constants.RESPONSE_KEYWORDS.NO_DATA);var isEmptyResponse=result.response===null||result.response.length===0||((_result$response=result.response)==null?void 0:_result$response.length)===1&&((_result$response$=result.response[0])==null?void 0:_result$response$.length)===0;if(hasNoData||isEmptyResponse){yield _logger.log.debug(`[${this.constructor.name}] NO DATA response or empty data received - interpreting as no DTCs present.`);return this.createEmptyResponse();}if(!this.ecuAddress&&result.rawString){var addresses=(0,_helpers.extractEcuAddresses)(result.rawString);if(addresses.length>0){var _addresses$;this.ecuAddress=(_addresses$=addresses[0])!=null?_addresses$:null;yield _logger.log.info(`[${this.constructor.name}] Extracted ECU address from response: ${this.ecuAddress}`);}}return{rawString:result.rawString,rawResponse:result.rawResponse,response:result.response,rawBytesResponseFromSendCommand:(_result$response2=result.response)!=null?_result$response2:[],isCan:this.isCan,protocolNumber:this.protocolNumber,ecuAddress:(_this$ecuAddress2=this.ecuAddress)!=null?_this$ecuAddress2:undefined};}catch(error){yield _logger.log.error(`[${this.constructor.name}] Error during retrieval attempt ${retryCount+1}:`,{error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:undefined});retryCount++;if(retryCount<maxRetries){yield _logger.log.debug(`[${this.constructor.name}] Retrying after error...`);yield this.delay(_constants.DELAYS_MS.RETRY);}}}yield _logger.log.error(`[${this.constructor.name}] Failed to retrieve DTCs for Mode ${this.mode} after ${maxRetries} attempts`);this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.ERROR;return null;});function retrieveRawDTCs(){return _retrieveRawDTCs.apply(this,arguments);}return retrieveRawDTCs;}())},{key:"processFramesByHeader",value:function processFramesByHeader(framesByHeader,line){var headerMatch=line.match(/^(?:[0-9A-F]{1,2}:)?(7E[8-F]|18DA[0-9A-F]{4})/i);if(headerMatch!=null&&headerMatch[1]){var headerKey=headerMatch[1].toUpperCase();if(!framesByHeader[headerKey]){framesByHeader[headerKey]=[];}var lineContent=line.substring(headerMatch[0].length).trim();if(lineContent){framesByHeader[headerKey].push(lineContent);}}else{var cleanedLine=(0,_helpers.cleanResponse)(line);if(cleanedLine&&!this.isErrorResponse(line)&&line!=='>'&&!line.includes('SEARCHING')){if(!framesByHeader['unknown']){framesByHeader['unknown']=[];}framesByHeader['unknown'].push(line.trim());}}}},{key:"handleCANResponse",value:(function(){var _handleCANResponse=(0,_asyncToGenerator2.default)(function*(response){var _this=this;if(!response)return[];var lines=response.split(/[\r\n]+/).filter(function(line){return line.trim()!=='';});if(lines.length===0)return[];var mightBeMultiFrame=lines.length>1&&lines.some(function(line){return /^\s*[0-9A-F]{1,2}:/.test(line)||/^[123]/.test((0,_helpers.cleanResponse)(line));});if(this.isCan&&mightBeMultiFrame){return yield this.handleCANMultiFrame(lines);}var processedFrames=lines.map(function(line){return _this.extractBytesFromSingleFrame(line);});return processedFrames.filter(function(frame){return frame.length>0;});});function handleCANResponse(_x){return _handleCANResponse.apply(this,arguments);}return handleCANResponse;}())},{key:"processRawResponse",value:(function(){var _processRawResponse=(0,_asyncToGenerator2.default)(function*(response){if(!response)return[];if(this.isCan){return yield this.handleCANResponse(response);}else if(this.protocolType===BaseDTCRetriever.PROTOCOL_TYPES.KWP){return this.handleKWPResponse(response);}else{var cleanedResponse=(0,_helpers.cleanResponse)(response);var allBytes=this.extractBytesFromSingleFrame(cleanedResponse);return allBytes.length>0?[allBytes]:[];}});function processRawResponse(_x2){return _processRawResponse.apply(this,arguments);}return processRawResponse;}())},{key:"extractBytesFromSingleFrame",value:function extractBytesFromSingleFrame(line){if(!line)return[];var dataPart=line.trim().toUpperCase();dataPart=dataPart.replace(/^\s*[0-9A-F]{1,2}:\s*/,'');if(dataPart.startsWith(this.responsePrefix)){dataPart=dataPart.substring(this.responsePrefix.length);}if(this.isHeaderEnabled){if(this.isCan){if(this.headerFormat===BaseDTCRetriever.HEADER_FORMATS.CAN_11BIT&&BaseDTCRetriever.CAN_11BIT_HEADER.test(dataPart)){dataPart=dataPart.substring(3);}else if(this.headerFormat===BaseDTCRetriever.HEADER_FORMATS.CAN_29BIT&&BaseDTCRetriever.CAN_29BIT_HEADER.test(dataPart)){dataPart=dataPart.substring(6);}}else if(this.protocolType===BaseDTCRetriever.PROTOCOL_TYPES.KWP&&BaseDTCRetriever.KWP_HEADER.test(dataPart)){if(dataPart.length>=6)dataPart=dataPart.substring(6);}else if(this.protocolType===BaseDTCRetriever.PROTOCOL_TYPES.ISO9141&&BaseDTCRetriever.ISO9141_HEADER.test(dataPart)){if(dataPart.length>=6)dataPart=dataPart.substring(6);}else if(this.protocolType===BaseDTCRetriever.PROTOCOL_TYPES.J1850&&BaseDTCRetriever.J1850_HEADER.test(dataPart)){if(dataPart.length>=6)dataPart=dataPart.substring(6);}}dataPart=dataPart.replace(/[^0-9A-F]/g,'');var bytes=[];for(var i=0;i+1<dataPart.length;i+=2){bytes.push(dataPart.substring(i,i+2));}return bytes;}},{key:"handleCANMultiFrame",value:(function(){var _handleCANMultiFrame=(0,_asyncToGenerator2.default)(function*(lines){yield _logger.log.debug(`[${this.constructor.name}] Detected multi-frame CAN response with ${lines.length} lines. Processing...`);var framesByHeader={};for(var line of lines){this.processFramesByHeader(framesByHeader,line);}var result=[];for(var _ref2 of Object.entries(framesByHeader)){var _ref3=(0,_slicedToArray2.default)(_ref2,2);var header=_ref3[0];var frames=_ref3[1];yield _logger.log.debug(`[${this.constructor.name}] Processing ${frames.length} frame(s) for header ${header}`);if(header==='unknown'){for(var frame of frames){var bytes=this.extractBytesFromSingleFrame(frame);if(bytes.length>0){result.push(bytes);}}continue;}var combinedData='';var expectedFrameIndex=1;var isMultiFrameSequenceActive=false;var totalLengthExpected=0;for(var _frame of frames){var dataPart=_frame.replace(/\s/g,'');if(!dataPart)continue;var frameTypeNibble=dataPart.substring(0,1);if(frameTypeNibble==='0'){var length=parseInt(dataPart.substring(1,2),16);if(!isNaN(length)&&length>0&&length<=7){combinedData=dataPart.substring(2,2+length*2);yield _logger.log.debug(`[${this.constructor.name}] Header ${header}: Found Single Frame (SF), length=${length}, data=${combinedData}`);break;}else{yield _logger.log.warn(`[${this.constructor.name}] Header ${header}: Invalid Single Frame PCI: ${dataPart}`);}}else if(frameTypeNibble==='1'){if(isMultiFrameSequenceActive){yield _logger.log.warn(`[${this.constructor.name}] Header ${header}: Received First Frame while already in a multi-frame sequence. Resetting sequence.`);}var lengthHex=dataPart.substring(1,4);totalLengthExpected=parseInt(lengthHex,16);if(!isNaN(totalLengthExpected)&&totalLengthExpected>7){combinedData=dataPart.substring(4);isMultiFrameSequenceActive=true;expectedFrameIndex=1;yield _logger.log.debug(`[${this.constructor.name}] Header ${header}: Found First Frame (FF), totalLength=${totalLengthExpected}, initialData=${combinedData}`);}else{yield _logger.log.warn(`[${this.constructor.name}] Header ${header}: Invalid First Frame PCI or length: ${dataPart}`);isMultiFrameSequenceActive=false;combinedData='';}}else if(frameTypeNibble==='2'&&isMultiFrameSequenceActive){var sequenceNibble=dataPart.substring(1,2);var sequenceNumber=parseInt(sequenceNibble,16);if(!isNaN(sequenceNumber)){if(sequenceNumber===expectedFrameIndex%16){combinedData+=dataPart.substring(2);expectedFrameIndex++;yield _logger.log.debug(`[${this.constructor.name}] Header ${header}: Found Consecutive Frame (CF), sequence=${sequenceNumber}, appendedData=${dataPart.substring(2)}`);}else{yield _logger.log.warn(`[${this.constructor.name}] Header ${header}: Unexpected CF sequence. Expected ${expectedFrameIndex%16}, got ${sequenceNumber}. Frame: ${dataPart}. Resetting sequence.`);isMultiFrameSequenceActive=false;combinedData='';break;}}else{yield _logger.log.warn(`[${this.constructor.name}] Header ${header}: Invalid Consecutive Frame PCI: ${dataPart}`);}}else if(frameTypeNibble==='3'){yield _logger.log.debug(`[${this.constructor.name}] Header ${header}: Ignoring Flow Control Frame (FC): ${dataPart}`);}else{yield _logger.log.debug(`[${this.constructor.name}] Header ${header}: Treating as single/unknown frame data: ${_frame}`);if(!isMultiFrameSequenceActive){combinedData=dataPart;break;}}if(isMultiFrameSequenceActive&&combinedData.length>=totalLengthExpected*2){yield _logger.log.debug(`[${this.constructor.name}] Header ${header}: Multi-frame message complete. Expected ${totalLengthExpected} bytes, received ${combinedData.length/2}.`);combinedData=combinedData.substring(0,totalLengthExpected*2);break;}}if(combinedData){var _bytes=[];for(var i=0;i+1<combinedData.length;i+=2){_bytes.push(combinedData.substring(i,i+2));}if(_bytes.length>0){result.push(_bytes);}}else if(header!=='unknown'){yield _logger.log.warn(`[${this.constructor.name}] No valid data assembled for header ${header}.`);}}return result;});function handleCANMultiFrame(_x3){return _handleCANMultiFrame.apply(this,arguments);}return handleCANMultiFrame;}())},{key:"sendCommandWithTiming",value:(function(){var _sendCommandWithTiming=(0,_asyncToGenerator2.default)(function*(command,timeout){var effectiveTimeout=timeout!=null?timeout:BaseDTCRetriever.COMMAND_TIMEOUT;if(!this.isCan){effectiveTimeout=timeout!=null?timeout:BaseDTCRetriever.DATA_TIMEOUT;yield _logger.log.debug(`[${this.constructor.name}] Using longer timeout (${effectiveTimeout}ms) for non-CAN protocol.`);}else{effectiveTimeout=timeout!=null?timeout:BaseDTCRetriever.COMMAND_TIMEOUT;}yield _logger.log.debug(`[${this.constructor.name}] Sending command "${command}" with timeout ${effectiveTimeout}ms`);return yield this.sendCommand(command,effectiveTimeout);});function sendCommandWithTiming(_x4,_x5){return _sendCommandWithTiming.apply(this,arguments);}return sendCommandWithTiming;}())},{key:"tryOptimizeFlowControl",value:(function(){var _tryOptimizeFlowControl=(0,_asyncToGenerator2.default)(function*(canID){if(!this.isCan){yield _logger.log.debug(`[${this.constructor.name}] Skipping flow control optimization for non-CAN protocol.`);return false;}var flowControlHeader=canID;if(!flowControlHeader){flowControlHeader=this.headerFormat===BaseDTCRetriever.HEADER_FORMATS.CAN_11BIT?'7E0':'18DA10F1';}var ecuResponseHeader=this.headerFormat===BaseDTCRetriever.HEADER_FORMATS.CAN_11BIT?'7E8':'18DAF110';yield _logger.log.debug(`[${this.constructor.name}] Optimizing CAN flow control. Target ECU Response Header: ${ecuResponseHeader}`);var flowControlConfigs=[{fcsh:ecuResponseHeader,fcsd:'300000',fcsm:'1',desc:'Standard (BS=0, ST=0, Mode=1)'},{fcsh:ecuResponseHeader,fcsd:'300000',fcsm:'0',desc:'No Wait (BS=0, ST=0, Mode=0)'},{fcsh:ecuResponseHeader,fcsd:'300008',fcsm:'1',desc:'Extended Wait (BS=0, ST=8ms, Mode=1)'}];for(var config of flowControlConfigs){yield _logger.log.debug(`[${this.constructor.name}] Trying Flow Control: ${config.desc}`);try{yield this.sendCommand(`ATFCSH${config.fcsh}`,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);yield this.sendCommand(`ATFCSD${config.fcsd}`,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);yield this.sendCommand(`ATFCSM${config.fcsm}`,2000);yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);var testResponse=yield this.sendCommandWithTiming(this.mode);if(testResponse&&!this.isErrorResponse(testResponse)&&!testResponse.includes(_constants.RESPONSE_KEYWORDS.BUFFER_FULL)){yield _logger.log.info(`[${this.constructor.name}] Flow control optimization successful with: ${config.desc}`);return true;}else{yield _logger.log.debug(`[${this.constructor.name}] Flow control config (${config.desc}) did not yield valid response: ${testResponse!=null?testResponse:'null'}`);}}catch(error){yield _logger.log.warn(`[${this.constructor.name}] Flow control config failed (${config.desc}):`,{error:error instanceof Error?error.message:String(error)});}yield this.delay(_constants.DELAYS_MS.COMMAND_SHORT);}yield _logger.log.warn(`[${this.constructor.name}] Could not optimize flow control after trying all configurations.`);return false;});function tryOptimizeFlowControl(_x6){return _tryOptimizeFlowControl.apply(this,arguments);}return tryOptimizeFlowControl;}())},{key:"verifyAndGetResponse",value:(function(){var _verifyAndGetResponse=(0,_asyncToGenerator2.default)(function*(){try{if(this.protocolState!==BaseDTCRetriever.PROTOCOL_STATES.READY){yield _logger.log.warn(`[${this.constructor.name}] Protocol not ready (State: ${this.protocolState}). Aborting command ${this.mode}.`);this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.ERROR;return null;}var result=yield this.sendCommandWithTiming(this.mode);if(result===null){yield _logger.log.warn(`[${this.constructor.name}] No response received for command ${this.mode}.`);return null;}if(this.isErrorResponse(result)){yield _logger.log.warn(`[${this.constructor.name}] Error response received for command ${this.mode}: ${result}`);if(result.includes('UNABLE')||result.includes('BUS ERROR')||result.includes('TIMEOUT')){this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.ERROR;}return null;}var needsFlowControlCheck=this.isCan&&(result.includes(_constants.RESPONSE_KEYWORDS.BUFFER_FULL)||result.includes(_constants.RESPONSE_KEYWORDS.FB_ERROR)||result.length>0&&result.length<10&&!result.includes(_constants.RESPONSE_KEYWORDS.NO_DATA));if(needsFlowControlCheck){yield _logger.log.debug(`[${this.constructor.name}] Detected potential CAN flow control issue or incomplete response. Response: ${result}. Attempting optimization...`);var potentialEcuAddress=this.extractEcuAddress(result);var flowControlSuccess=yield this.tryOptimizeFlowControl(potentialEcuAddress!=null?potentialEcuAddress:undefined);if(flowControlSuccess){yield _logger.log.debug(`[${this.constructor.name}] Retrying command ${this.mode} after flow control optimization...`);var retryResult=yield this.sendCommandWithTiming(this.mode);if(retryResult&&!this.isErrorResponse(retryResult)){yield _logger.log.info(`[${this.constructor.name}] Successfully received response after flow control optimization.`);var _processedData=yield this.processRawResponse(retryResult);var _rawBytes=Array.from(retryResult).map(function(c){return c.charCodeAt(0);});return{rawString:retryResult,rawResponse:_rawBytes,response:_processedData};}else{yield _logger.log.warn(`[${this.constructor.name}] Command ${this.mode} still failed or gave error after flow control optimization. Response: ${retryResult!=null?retryResult:'null'}`);}}else{yield _logger.log.warn(`[${this.constructor.name}] Flow control optimization failed. Proceeding with original response.`);}}yield _logger.log.debug(`[${this.constructor.name}] Processing response for command ${this.mode}: ${result}`);var processedData=yield this.processRawResponse(result);var rawBytes=Array.from(result).map(function(c){return c.charCodeAt(0);});return{rawString:result,rawResponse:rawBytes,response:processedData};}catch(error){yield _logger.log.error(`[${this.constructor.name}] Error during command execution or response processing for ${this.mode}:`,{error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:undefined});this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.ERROR;return null;}});function verifyAndGetResponse(){return _verifyAndGetResponse.apply(this,arguments);}return verifyAndGetResponse;}())},{key:"handleKWPResponse",value:function handleKWPResponse(response){if(!response)return[];var lines=response.split(/[\r\n]+/).filter(function(line){return line.trim()!=='';});var result=[];for(var line of lines){var processedLine=line.trim();var bytes=this.extractBytesFromSingleFrame(processedLine);if(bytes.length>0){result.push(bytes);}}return result.filter(function(frame){return frame.length>0;});}},{key:"resetState",value:function resetState(){this.isCan=false;this.protocolNumber=0;this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.UNKNOWN;this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.UNKNOWN;this.ecuAddress=null;this.protocolState=BaseDTCRetriever.PROTOCOL_STATES.INITIALIZED;this.isHeaderEnabled=false;this.isEchoEnabled=false;this.lineFeedsDisabled=false;this.spacesDisabled=false;void _logger.log.debug(`[${this.constructor.name}] State reset.`);}},{key:"detectProtocol",value:(function(){var _detectProtocol=(0,_asyncToGenerator2.default)(function*(){yield _logger.log.debug(`[${this.constructor.name}] Detecting protocol (ATDPN)...`);try{var protocolResponse=yield this.sendCommand(_constants.ELM_COMMANDS.GET_PROTOCOL_NUM,2000);if(!protocolResponse||this.isErrorResponse(protocolResponse)){yield _logger.log.warn(`[${this.constructor.name}] Failed to get protocol number. Response: ${protocolResponse!=null?protocolResponse:'null'}`);this.updateProtocolInfo(-1);return false;}var cleanedResponse=(0,_helpers.cleanResponse)(protocolResponse);var protocolNum=-1;if(cleanedResponse&&/^[A-F0-9]{1,2}$/i.test(cleanedResponse)){protocolNum=parseInt(cleanedResponse,16);}else{yield _logger.log.warn(`[${this.constructor.name}] Unexpected format for protocol number response: ${cleanedResponse}`);}this.updateProtocolInfo(protocolNum);yield _logger.log.debug(`[${this.constructor.name}] Protocol detection complete. Number: ${this.protocolNumber}, Type: ${this.protocolType}, isCAN: ${this.isCan}, Header Format: ${this.headerFormat}`);return this.protocolType!==BaseDTCRetriever.PROTOCOL_TYPES.UNKNOWN;}catch(error){yield _logger.log.error(`[${this.constructor.name}] Error detecting protocol:`,{error:error instanceof Error?error.message:String(error)});this.updateProtocolInfo(-1);return false;}});function detectProtocol(){return _detectProtocol.apply(this,arguments);}return detectProtocol;}())},{key:"updateProtocolInfo",value:function updateProtocolInfo(protocolNum){this.protocolNumber=protocolNum;if(protocolNum>=6&&protocolNum<=20){this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.CAN;if(protocolNum===10){this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.CAN_29BIT;}else if(protocolNum>=6&&protocolNum<=9){this.headerFormat=protocolNum%2===0?BaseDTCRetriever.HEADER_FORMATS.CAN_11BIT:BaseDTCRetriever.HEADER_FORMATS.CAN_29BIT;}else{this.headerFormat=protocolNum%2===0?BaseDTCRetriever.HEADER_FORMATS.CAN_11BIT:BaseDTCRetriever.HEADER_FORMATS.CAN_29BIT;}this.isCan=true;}else if(protocolNum===3){this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.ISO9141;this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.ISO9141;this.isCan=false;}else if(protocolNum===4||protocolNum===5){this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.KWP;this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.KWP;this.isCan=false;}else if(protocolNum===1||protocolNum===2){this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.J1850;this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.J1850;this.isCan=false;}else{this.protocolType=BaseDTCRetriever.PROTOCOL_TYPES.UNKNOWN;this.headerFormat=BaseDTCRetriever.HEADER_FORMATS.UNKNOWN;this.isCan=false;}}}]);}();BaseDTCRetriever.PROTOCOL_TYPES={CAN:'CAN',KWP:'KWP',ISO9141:'ISO9141',J1850:'J1850',UNKNOWN:'UNKNOWN'};BaseDTCRetriever.HEADER_FORMATS={CAN_11BIT:'11bit',CAN_29BIT:'29bit',KWP:'kwp',ISO9141:'iso9141',J1850:'j1850',UNKNOWN:'unknown'};BaseDTCRetriever.PROTOCOL_STATES={INITIALIZED:'INITIALIZED',CONFIGURING:'CONFIGURING',READY:'READY',ERROR:'ERROR'};BaseDTCRetriever.ERROR_RESPONSES=[_constants.RESPONSE_KEYWORDS.UNABLE_TO_CONNECT,_constants.RESPONSE_KEYWORDS.BUS_INIT,_constants.RESPONSE_KEYWORDS.CAN_ERROR,_constants.RESPONSE_KEYWORDS.BUS_ERROR,_constants.RESPONSE_KEYWORDS.FB_ERROR,_constants.RESPONSE_KEYWORDS.DATA_ERROR,_constants.RESPONSE_KEYWORDS.ERROR,_constants.RESPONSE_KEYWORDS.BUFFER_FULL,_constants.RESPONSE_KEYWORDS.BUS_BUSY,_constants.RESPONSE_KEYWORDS.NO_DATA,_constants.RESPONSE_KEYWORDS.RX_ERROR,_constants.RESPONSE_KEYWORDS.STOPPED,'TIMEOUT','7F','UNABLE','ACT ALERT','ERR','?'].map(function(e){return e.replace(/\s/g,'').toUpperCase();});BaseDTCRetriever.CAN_11BIT_HEADER=/^7E[8-F]/i;BaseDTCRetriever.CAN_29BIT_HEADER=/^18DAF1/i;BaseDTCRetriever.KWP_HEADER=/^(48|68|81)/i;BaseDTCRetriever.ISO9141_HEADER=/^(48|6B)/i;BaseDTCRetriever.J1850_HEADER=/^(41|48|6B|A8|B8)/i;BaseDTCRetriever.SERVICE_MODES={MODE03:'03',MODE07:'07',MODE0A:'0A'};BaseDTCRetriever.DATA_TIMEOUT=10000;BaseDTCRetriever.COMMAND_TIMEOUT=5000; //# sourceMappingURL=BaseDTCRetriever.js.map