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 • 14.6 kB
JavaScript
Object.defineProperty(exports,"__esModule",{value:true});exports.cleanResponse=exports.assembleMultiFrameResponse=void 0;exports.extractEcuAddresses=extractEcuAddresses;exports.parseVinFromResponse=exports.parseDtcsFromResponse=exports.isVinResponseFrame=exports.isResponseOk=exports.isResponseError=exports.isIsoTpFrameIndicator=exports.extractVoltage=exports.extractProtocolNumber=void 0;var _logger=require("../../utils/logger");var _constants=require("./constants");var _ecuUtils=require("./ecuUtils");var cleanResponse=exports.cleanResponse=function cleanResponse(response){if(!response)return'';return response.replace(/>/g,'').replace(/SEARCHING\.\.\./i,'').replace(/^ATZ[\r\n]*/i,'').replace(/^ATE0[\r\n]*/i,'').replace(/^ATL0[\r\n]*/i,'').replace(/^ATS0[\r\n]*/i,'').replace(/^ATH[01][\r\n]*/i,'').replace(/^ATSP[0-9A-F][\r\n]*/i,'').replace(/^ATTP[0-9A-F][\r\n]*/i,'').replace(/^ATRV[\r\n]*/i,'').replace(/[\r\n\t\0]/g,' ').replace(/\s+/g,' ').trim().toUpperCase();};var isResponseOk=exports.isResponseOk=function isResponseOk(response){if(!response)return false;var cleanedResponse=response.trim().toUpperCase();return cleanedResponse==='OK'||/^[0-9A-F\s]+$/.test(cleanedResponse);};var isResponseError=exports.isResponseError=function isResponseError(response){if(response===null)return true;if(!response)return false;var cleanedUpper=response.replace(/\s/g,'').toUpperCase();if(cleanedUpper.length===0)return false;var errorKeywords=[_constants.RESPONSE_KEYWORDS.ERROR,_constants.RESPONSE_KEYWORDS.UNABLE_TO_CONNECT.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.BUS_INIT.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.CAN_ERROR.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.BUS_ERROR.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.FB_ERROR.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.DATA_ERROR.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.BUFFER_FULL.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.RX_ERROR.replace(/\s/g,''),_constants.RESPONSE_KEYWORDS.STOPPED,_constants.RESPONSE_KEYWORDS.TIMEOUT,'7F','UNABLE','ACT ALERT','ERR'].map(function(e){return e.replace(/\s/g,'').toUpperCase();});if(response.trim()===_constants.RESPONSE_KEYWORDS.QUESTION_MARK){return true;}if(errorKeywords.some(function(keyword){return cleanedUpper.includes(keyword);})){return true;}return false;};var extractVoltage=exports.extractVoltage=function extractVoltage(response){if(!response)return null;var cleaned=response.replace(/[>\r\n\t\0]/g,'');var match=cleaned.match(/(\d{1,2}(?:\.\d{1,2})?V)/i);return match!=null&&match[1]?match[1].toUpperCase():null;};var extractProtocolNumber=exports.extractProtocolNumber=function extractProtocolNumber(response){if(!response)return null;var cleaned=response.replace(/[>\r\n\t\0\s]/g,'').toUpperCase();var match=cleaned.match(/^(A?)([0-9A-F]{1,2})$/i);if(match){var isAuto=match[1]==='A';var protocolHex=match[2];try{var parsedProtocol=protocolHex?parseInt(protocolHex,16):null;if(parsedProtocol!==null&&parsedProtocol>=_constants.PROTOCOL.AUTO&&parsedProtocol<=_constants.PROTOCOL.ISO_15765_4_CAN_29BIT_250K_8){if(isAuto){void _logger.log.debug(`[Helper] Auto-detected protocol number: ${parsedProtocol} (from ${response})`);}return parsedProtocol;}else{void _logger.log.warn(`[Helper] Extracted protocol number out of expected range: ${parsedProtocol} from ${response}`);}}catch(error){var errorMsg=error instanceof Error?error.message:String(error);void _logger.log.error(`[Helper] Failed to parse protocol number from ${protocolHex} in ${response}`,{error:errorMsg});}}else{if(cleaned.includes('J1850PWM'))return _constants.PROTOCOL.SAE_J1850_PWM;if(cleaned.includes('J1850VPW'))return _constants.PROTOCOL.SAE_J1850_VPW;if(cleaned.includes('ISO9141'))return _constants.PROTOCOL.ISO_9141_2;if(cleaned.includes('KWP'))return _constants.PROTOCOL.ISO_14230_4_KWP_FAST;if(cleaned.includes('CAN')){return _constants.PROTOCOL.ISO_15765_4_CAN_11BIT_500K;}}return null;};function extractEcuAddresses(rawResponse){if(!rawResponse)return[];var addresses=new Set();var lines=rawResponse.split(/[\r\n]+/).filter(function(line){return line.trim().length>0;});for(var line of lines){var _match,_match2,_match3,_match4,_match5;var dataPart=line.trim().toUpperCase();dataPart=dataPart.replace(/^\s*[0-9A-F]{1,2}:\s*/,'');if(!/^[0-9A-F\s]+$/.test(dataPart)||dataPart===_constants.RESPONSE_KEYWORDS.OK||dataPart===_constants.RESPONSE_KEYWORDS.NO_DATA||isResponseError(dataPart)){continue;}var match=dataPart.match(/^(7E[89ABCDEF])([0-9A-F]{2})/i);if((_match=match)!=null&&_match[1]&&match[2]){addresses.add(match[1]);continue;}match=dataPart.match(/^(18DAF1[0-9A-F]{2})/i);if((_match2=match)!=null&&_match2[1]&&dataPart.length>match[1].length){addresses.add(match[1]);continue;}match=dataPart.match(/^(18DA[0-9A-F]{2}F1)/i);if((_match3=match)!=null&&_match3[1]&&dataPart.length>match[1].length){addresses.add(match[1]);continue;}match=dataPart.match(/^(18DB33F1)/i);if((_match4=match)!=null&&_match4[1]&&dataPart.length>match[1].length){continue;}match=dataPart.match(/^([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})/i);if((_match5=match)!=null&&_match5[1]&&match[2]&&match[3]){var formatTarget=match[1];var targetSource=match[2];var sourceLengthOrData=match[3];if(formatTarget==='48'&&targetSource==='6B'){addresses.add(sourceLengthOrData);continue;}if(formatTarget.startsWith('8')){addresses.add(targetSource);continue;}if(formatTarget.startsWith('4')||formatTarget.startsWith('6')){if(targetSource!=='F1'){addresses.add(targetSource);}else if(sourceLengthOrData!=='F1'){addresses.add(sourceLengthOrData);}continue;}}}return Array.from(addresses);}var isVinResponseFrame=exports.isVinResponseFrame=function isVinResponseFrame(cleanedResponse){var dataPart=cleanedResponse.replace(/^(4902|0902)/,'').trim();return dataPart.startsWith('10')||/^[2][0-9A-F]/.test(dataPart);};var assembleMultiFrameResponse=exports.assembleMultiFrameResponse=function assembleMultiFrameResponse(rawResponse){if(!rawResponse)return'';void _logger.log.debug(`[Helper:assemble] Input: ${rawResponse}`);var lines=rawResponse.split(/[\r\n]+/).map(function(line){return line.trim();}).filter(function(line){return line.length>0&&!line.startsWith(_constants.RESPONSE_KEYWORDS.PROMPT)&&!isResponseError(line)&&line!==_constants.RESPONSE_KEYWORDS.OK;});var assembledData='';var isMultiFrameSequence=false;var expectedFrameIndex=1;var totalExpectedLength=0;for(var line of lines){var processedLine=line.replace(/^\s*[0-9A-F]{1,2}:\s*/,'');processedLine=processedLine.replace(/\s/g,'');if(isIsoTpFrameIndicator(processedLine)){var frameType=parseInt(processedLine.substring(0,1),16);if(frameType===1){if(isMultiFrameSequence){void _logger.log.warn('[Helper:assemble] Received First Frame while already in sequence. Resetting.',{line:line});assembledData='';}isMultiFrameSequence=true;expectedFrameIndex=1;var lengthHex=processedLine.substring(1,4);totalExpectedLength=parseInt(lengthHex,16);if(isNaN(totalExpectedLength)){void _logger.log.warn('[Helper:assemble] Invalid First Frame length.',{line:line});isMultiFrameSequence=false;processedLine='';}else{processedLine=processedLine.substring(4);void _logger.log.debug('[Helper:assemble] First Frame found.',{line:line,length:totalExpectedLength,initialData:processedLine});}}else if(frameType===2&&isMultiFrameSequence){var sequenceNumber=parseInt(processedLine.substring(1,2),16);if(isNaN(sequenceNumber)){void _logger.log.warn('[Helper:assemble] Invalid Consecutive Frame sequence number.',{line:line});processedLine='';}else if(sequenceNumber!==expectedFrameIndex%16){void _logger.log.warn(`[Helper:assemble] Unexpected Consecutive Frame sequence. Expected ${expectedFrameIndex%16}, got ${sequenceNumber}`,{line:line});isMultiFrameSequence=false;assembledData='';processedLine='';}else{expectedFrameIndex++;processedLine=processedLine.substring(2);void _logger.log.debug('[Helper:assemble] Consecutive Frame found.',{line:line,sequence:sequenceNumber,data:processedLine});}}else if(frameType===3){void _logger.log.debug('[Helper:assemble] Discarding Flow Control frame:',{line:line});processedLine='';}else{if(frameType===0){var length=parseInt(processedLine.substring(1,2),16);if(!isNaN(length)&&length>0&&length<=7){processedLine=processedLine.substring(2,2+length*2);void _logger.log.debug('[Helper:assemble] Single Frame found.',{line:line,length:length,data:processedLine});}else{void _logger.log.warn('[Helper:assemble] Invalid Single Frame length/format.',{line:line});processedLine='';}}else{void _logger.log.debug('[Helper:assemble] Treating as non-ISO-TP data or end of sequence.',{line:line});}isMultiFrameSequence=false;}}else{void _logger.log.debug('[Helper:assemble] Line does not have ISO-TP indicator.',{line:line});isMultiFrameSequence=false;}assembledData+=processedLine;if(isMultiFrameSequence&&totalExpectedLength>0&&assembledData.length>=totalExpectedLength*2){void _logger.log.debug(`[Helper:assemble] Multi-frame message complete. Expected ${totalExpectedLength}, got ${assembledData.length/2} bytes.`);assembledData=assembledData.substring(0,totalExpectedLength*2);isMultiFrameSequence=false;}}void _logger.log.debug(`[Helper:assemble] Output: ${assembledData}`);return assembledData;};var parseVinFromResponse=exports.parseVinFromResponse=function parseVinFromResponse(assembledHexData){if(!assembledHexData)return null;void _logger.log.debug(`[Helper:parseVin] Input Hex: ${assembledHexData}`);var vinSignatureIndex=assembledHexData.indexOf('4902');var payloadStartIndex=-1;if(vinSignatureIndex!==-1){if(assembledHexData.substring(vinSignatureIndex+4,vinSignatureIndex+6)==='01'){payloadStartIndex=vinSignatureIndex+6;}else{payloadStartIndex=vinSignatureIndex+4;void _logger.log.warn(`[Helper:parseVin] VIN response '4902' found, but not followed by expected count '01'. Assuming payload starts immediately after.`);}}else{vinSignatureIndex=assembledHexData.indexOf('0902');if(vinSignatureIndex!==-1){if(assembledHexData.substring(vinSignatureIndex+4,vinSignatureIndex+6)==='01'){payloadStartIndex=vinSignatureIndex+6;}else{payloadStartIndex=vinSignatureIndex+4;void _logger.log.warn(`[Helper:parseVin] VIN response '0902' found, but not followed by expected count '01'. Assuming payload starts immediately after.`);}}}if(payloadStartIndex===-1){void _logger.log.warn(`[Helper:parseVin] VIN signature '4902' or '0902' not found. Cannot reliably parse VIN.`,{data:assembledHexData});if(assembledHexData.length===34){void _logger.log.warn(`[Helper:parseVin] No signature found, but data length is 34 hex chars. Attempting to parse as VIN.`);payloadStartIndex=0;}else{return null;}}var hexPayload=assembledHexData.substring(payloadStartIndex);var cleanPayload=hexPayload.replace(/00+$/i,'');if(cleanPayload.length===0){void _logger.log.warn('[Helper:parseVin] VIN payload is empty after cleaning.');return null;}var expectedHexLength=17*2;var trimmedPayload=cleanPayload.length>expectedHexLength+6?cleanPayload.substring(0,expectedHexLength):cleanPayload;try{var bytes=(0,_ecuUtils.hexToBytes)(trimmedPayload);var vin=(0,_ecuUtils.bytesToString)(bytes);var finalVin=vin.replace(/[^A-HJ-NPR-Z0-9]/gi,'');void _logger.log.debug(`[Helper:parseVin] Decoded VIN attempt: "${finalVin}" (Length: ${finalVin.length})`);if(finalVin.length===17&&/^[A-HJ-NPR-Z0-9]{17}$/i.test(finalVin)){void _logger.log.debug(`[Helper:parseVin] Parsed VIN appears valid: ${finalVin}`);return finalVin;}else if(finalVin.length>5){void _logger.log.warn(`[Helper:parseVin] Parsed VIN "${finalVin}" has unexpected format/length (${finalVin.length}). Returning potentially incorrect value.`);return finalVin;}else{void _logger.log.warn(`[Helper:parseVin] Failed to decode a valid VIN from payload hex: ${trimmedPayload}`);return null;}}catch(error){var errorMsg=error instanceof Error?error.message:String(error);void _logger.log.error(`[Helper:parseVin] Error decoding VIN hex "${trimmedPayload}":`,{error:errorMsg});return null;}};var parseDtcsFromResponse=exports.parseDtcsFromResponse=function parseDtcsFromResponse(responseData,modePrefix){if(!responseData)return null;void _logger.log.debug(`[Helper] Parsing DTC data starting with mode ${modePrefix}: ${responseData}`);var startIndex=responseData.indexOf(modePrefix);if(startIndex===-1){if(responseData===modePrefix){void _logger.log.debug(`[Helper] DTC response is just prefix ${modePrefix}, indicating zero DTCs.`);return[];}void _logger.log.warn(`[Helper] DTC response prefix ${modePrefix} not found in data: ${responseData}`);return null;}var dtcHexData=responseData.substring(startIndex+modePrefix.length);if(dtcHexData.length>=2){var potentialCountHex=dtcHexData.substring(0,2);if(/^[0-9A-F]{2}$/.test(potentialCountHex)){var potentialCount=parseInt(potentialCountHex,16);var expectedLength=potentialCount*4;var remainingDataLength=dtcHexData.length-2;if(!isNaN(potentialCount)&&potentialCount<50&&remainingDataLength%4===0&&remainingDataLength===expectedLength){void _logger.log.debug(`[Helper] Assuming first byte ${potentialCountHex} is DTC count (${potentialCount}), skipping.`);dtcHexData=dtcHexData.substring(2);}else{void _logger.log.debug(`[Helper] First byte ${potentialCountHex} after prefix doesn't look like a reliable DTC count. Parsing all subsequent data.`);}}}var dtcs=[];var cleanDtcHexData=dtcHexData.replace(/(0000)+$/,'');if(cleanDtcHexData.length%4!==0){void _logger.log.warn(`[Helper] DTC data length (${cleanDtcHexData.length}) is not a multiple of 4 after removing trailing 0000s. Data: ${cleanDtcHexData}`);}for(var i=0;i+4<=cleanDtcHexData.length;i+=4){var dtcPair=cleanDtcHexData.substring(i,i+4);if(dtcPair==='0000')continue;if(!/^[0-9A-F]{4}$/i.test(dtcPair)){void _logger.log.warn(`[Helper] Skipping invalid hex sequence in DTC data: ${dtcPair}`);continue;}var byte1=parseInt(dtcPair.substring(0,2),16);var byte2=parseInt(dtcPair.substring(2,4),16);var firstChar=void 0;var firstTwoBits=byte1>>6;switch(firstTwoBits){case 0:firstChar='P';break;case 1:firstChar='C';break;case 2:firstChar='B';break;case 3:firstChar='U';break;default:firstChar='?';}var secondCharDigit=byte1>>4&0x03;var lastThreeDigits=((byte1&0x0f)<<8|byte2).toString(16).toUpperCase().padStart(3,'0');var dtcCode=`${firstChar}${secondCharDigit}${lastThreeDigits}`;dtcs.push(dtcCode);}void _logger.log.debug(`[Helper] Parsed DTCs (Mode ${modePrefix}): ${dtcs.length>0?dtcs.join(', '):'None'}`);return dtcs;};var isIsoTpFrameIndicator=exports.isIsoTpFrameIndicator=function isIsoTpFrameIndicator(cleanedLine){return cleanedLine.startsWith('0')||cleanedLine.startsWith('1')||/^[2][0-9A-F]/.test(cleanedLine)||cleanedLine.startsWith('3');};
//# sourceMappingURL=helpers.js.map