UNPKG

obd-raw-data-parser

Version:

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

2 lines 10.8 kB
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.CanDecoder=void 0;var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));var _possibleConstructorReturn2=_interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));var _getPrototypeOf2=_interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));var _inherits2=_interopRequireDefault(require("@babel/runtime/helpers/inherits"));var _logger=require("../../logger");var _BaseDecoder2=require("./BaseDecoder");var _CanSingleFrame=require("./CanSingleFrame");var _utils=require("../../utils");var _dtcConverter=require("../utils/dtcConverter");function _callSuper(t,o,e){return o=(0,_getPrototypeOf2.default)(o),(0,_possibleConstructorReturn2.default)(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],(0,_getPrototypeOf2.default)(t).constructor):o.apply(t,e));}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t;})();}var CanDecoder=exports.CanDecoder=function(_BaseDecoder){function CanDecoder(modeResponse){var _this;(0,_classCallCheck2.default)(this,CanDecoder);_this=_callSuper(this,CanDecoder);_this.leftoverByte=null;_this.expectedDTCCount=0;_this.currentDTCCount=0;_this.rawDtcObjects=[];_this.modeResponse=modeResponse||0x43;_this.singleFrameDecoder=new _CanSingleFrame.CanSingleFrame(_this.modeResponse);_this.bindMethodsToSingleFrameDecoder();return _this;}(0,_inherits2.default)(CanDecoder,_BaseDecoder);return(0,_createClass2.default)(CanDecoder,[{key:"setModeResponse",value:function setModeResponse(response){this.modeResponse=response;this.singleFrameDecoder.setModeResponse(response);}},{key:"bindMethodsToSingleFrameDecoder",value:function bindMethodsToSingleFrameDecoder(){var _this2=this;Object.defineProperties(this.singleFrameDecoder,{setDTC:{value:this.setDTC.bind(this)},getModeResponseByte:{value:function value(){return _this2.modeResponse;}}});}},{key:"decodeDTCs",value:function decodeDTCs(rawResponseBytes){try{this.reset();var isMultiFrame=this._isMultiFrameResponse(rawResponseBytes);(0,_logger.log)('debug',`Response type: ${isMultiFrame?'multi-frame':'single-frame'}`);if(!isMultiFrame){return this.singleFrameDecoder.decodeDTCs(rawResponseBytes);}if(this._isEmptyAsciiFormat(rawResponseBytes)){(0,_logger.log)('debug','Detected empty ASCII hex format (4300AAA...), returning empty array');return[];}var isAsciiHexFormat=this._isAsciiHexFormat(rawResponseBytes);var isCarFormat=this._isCarFormat(rawResponseBytes);if(isAsciiHexFormat){(0,_logger.log)('debug','Detected ASCII hex format response, using special processing');if(isCarFormat){return this._processCarAsciiHexFormat(rawResponseBytes);}else{return this._processStandardAsciiHexFormat(rawResponseBytes);}}var dtcs=new Set();var rawDtcs=new Set();(0,_logger.log)('debug','Processing raw response bytes:',rawResponseBytes);for(var frameIndex=0;frameIndex<rawResponseBytes.length;frameIndex++){var frame=rawResponseBytes[frameIndex];var isCANFrame=false;if(!Array.isArray(frame)||frame.length<4){(0,_logger.log)('debug',`Frame ${frameIndex}: Skipping invalid byte array:`,frame);continue;}(0,_logger.log)('debug',`Processing Frame ${frameIndex}:`,frame);var bytes=[];isCANFrame=frame.length<=6;if(isCANFrame){(0,_logger.log)('debug',`Processing CAN frame ${frameIndex}`);bytes=this._extractBytesFromCANFrame(frame);}else{var frameType=this._determineFrameType(frame);if(frameType==='colon'){var colonIndex=frame.indexOf(58);bytes=this._extractBytesFromColonFrame(frame,colonIndex);}else{(0,_logger.log)('debug',`Frame ${frameIndex}: No colon found, using alternative decoding`);bytes=this._extractBytesFromNoColonFrame(frame);}}if(!bytes||bytes.length===0){(0,_logger.log)('debug',`Frame ${frameIndex}: No bytes extracted`);continue;}this._processDTCBytes(bytes,dtcs,rawDtcs,frameIndex,isCANFrame);}this.rawDtcObjects=Array.from(rawDtcs);var dtcArray=Array.from(dtcs);(0,_logger.log)('debug','Discovered DTC count:',dtcArray.length);return dtcArray;}catch(error){(0,_logger.log)('error','Failed to parse response:',error);return[];}}},{key:"reset",value:function reset(){this.rawDtcObjects=[];this.expectedDTCCount=0;this.currentDTCCount=0;this.leftoverByte=null;}},{key:"_extractBytesFromCANFrame",value:function _extractBytesFromCANFrame(frame){var dataBytes=frame.slice(2);return this._extractBytesFromData(dataBytes);}},{key:"_extractBytesFromData",value:function _extractBytesFromData(dataArray){var bytes=[];var currentNibble=-1;var hexPair='';for(var byte of dataArray){if(byte===13)break;var nibble=this._getNibbleValue(byte);if(nibble===-1)continue;if(currentNibble===-1){currentNibble=nibble;hexPair=nibble.toString(16).toLowerCase();}else{hexPair+=nibble.toString(16).toLowerCase();bytes.push(hexPair);currentNibble=-1;hexPair='';}}if(currentNibble!==-1){this.leftoverByte=currentNibble.toString(16).toLowerCase();}(0,_logger.log)('debug','Extracted bytes:',bytes);return bytes;}},{key:"_getNibbleValue",value:function _getNibbleValue(byte){if(byte>=48&&byte<=57)return byte-48;if(byte>=65&&byte<=70)return byte-55;if(byte>=97&&byte<=102)return byte-87;return-1;}},{key:"_processDTCBytes",value:function _processDTCBytes(bytes,dtcs,rawDtcs,frameIndex,isCANFrame){(0,_logger.log)('debug',`Frame ${frameIndex}: Processing DTCs, bytes:`,bytes);if(!bytes||bytes.length<1)return;if(this.leftoverByte!==null){bytes.unshift(this.leftoverByte);this.leftoverByte=null;}var startIndex=0;if(frameIndex===0){var firstByte=parseInt(bytes[0],16);if(firstByte===this.getModeResponseByte()){startIndex=1;if(bytes.length>1&&this.expectedDTCCount===0){var countByte=parseInt(bytes[1],16);this.expectedDTCCount=Math.floor(countByte/2);startIndex=2;}}}for(var i=startIndex;i<bytes.length;i+=2){if(i+1>=bytes.length){if(isCANFrame&&this.expectedDTCCount===0){(0,_logger.log)('warn','CAN frame has odd number of DTC bytes');}this.leftoverByte=bytes[i];break;}var byte1=bytes[i];var byte2=bytes[i+1];if(!byte1||!byte2||byte1==='00'&&byte2==='00'){continue;}var dtc=this._decodeDTC(byte1,byte2);if(dtc){rawDtcs.add(dtc);dtcs.add(dtc);this.setDTC(dtc);(0,_logger.log)('debug','Discovered DTC:',dtc);}}}},{key:"_decodeDTC",value:function _decodeDTC(byte1,byte2){try{var combinedHex=byte1.padStart(2,'0')+byte2.padStart(2,'0');return(0,_dtcConverter.hexToDTC)(combinedHex);}catch(error){(0,_logger.log)('error','Failed to decode DTC:',error);return null;}}},{key:"_dtcToString",value:function _dtcToString(dtc){return dtc;}},{key:"setDTC",value:function setDTC(dtc){(0,_logger.log)('debug',`Setting DTC: ${dtc}`);}},{key:"getModeResponseByte",value:function getModeResponseByte(){return this.modeResponse;}},{key:"_determineFrameType",value:function _determineFrameType(frame){var colonIndex=frame.indexOf(58);return colonIndex!==-1?'colon':'no-colon';}},{key:"_extractBytesFromColonFrame",value:function _extractBytesFromColonFrame(frame,colonIndex){var dataStartIndex=colonIndex+1;while(dataStartIndex<frame.length&&frame[dataStartIndex]===32){dataStartIndex++;}return this._extractBytesFromData(frame.slice(dataStartIndex));}},{key:"_extractBytesFromNoColonFrame",value:function _extractBytesFromNoColonFrame(frame){var dataStartIndex=0;while(dataStartIndex<frame.length&&frame[dataStartIndex]===32){dataStartIndex++;}return this._extractBytesFromData(frame.slice(dataStartIndex));}},{key:"parseDTCStatus",value:function parseDTCStatus(statusByte){return{milActive:(statusByte&0x80)!==0,dtcCount:statusByte&0x7f,currentError:(statusByte&0x20)!==0,pendingError:(statusByte&0x10)!==0,confirmedError:(statusByte&0x08)!==0,egrSystem:(statusByte&0x04)!==0,oxygenSensor:(statusByte&0x02)!==0,catalyst:(statusByte&0x01)!==0};}},{key:"_isMultiFrameResponse",value:function _isMultiFrameResponse(frames){if(!frames||frames.length<2)return false;var firstFrameString=(0,_utils.byteArrayToString)(frames[0]);if(firstFrameString.startsWith('0:')){return true;}return frames.some(function(frame){var frameString=(0,_utils.byteArrayToString)(frame);return /^[0-9]:/.test(frameString);});}},{key:"_isCarFormat",value:function _isCarFormat(frames){for(var frame of frames){var frameString=frame.map(function(byte){return String.fromCharCode(byte);}).join('');var modeResponseHex=this.modeResponse.toString(16).toUpperCase();if(frameString.includes(`${modeResponseHex}0204`)){return true;}}return false;}},{key:"_isEmptyAsciiFormat",value:function _isEmptyAsciiFormat(frames){var modeResponseHex=this.modeResponse.toString(16).toUpperCase();for(var frame of frames){if(frame.length<4)continue;var frameString=frame.map(function(byte){return String.fromCharCode(byte);}).join('');if(frameString.startsWith(`${modeResponseHex}00`)&&frameString.substring(4).replace(/[\r\n>]/g,'').match(/^A+$/i)){return true;}}return false;}},{key:"_isAsciiHexFormat",value:function _isAsciiHexFormat(frames){if(!frames||frames.length===0)return false;for(var frame of frames){if(frame.length<2)continue;var firstChar=String.fromCharCode(frame[0]);var secondChar=String.fromCharCode(frame[1]);if(firstChar==='4'&&(secondChar==='3'||secondChar==='7'||secondChar==='A'||secondChar==='a')){return true;}}return false;}},{key:"_processStandardAsciiHexFormat",value:function _processStandardAsciiHexFormat(frames){return this.singleFrameDecoder.decodeDTCs(frames);}},{key:"_processCarAsciiHexFormat",value:function _processCarAsciiHexFormat(frames){var dtcs=new Set();var modeResponseHex=(0,_utils.toHexString)(this.modeResponse).toUpperCase();for(var frame of frames){if(frame.length<4)continue;var frameString=(0,_utils.byteArrayToString)(frame).replace(/[\r\n>]/g,'');(0,_logger.log)('debug','Processing ASCII hex frame:',frameString);if(!frameString.startsWith(modeResponseHex)){(0,_logger.log)('debug',`Frame doesn't start with expected mode response ${modeResponseHex}`);continue;}var dtcHexString=frameString.substring(2);for(var i=0;i<dtcHexString.length;i+=4){if(i+3>=dtcHexString.length)break;var byte1Hex=dtcHexString.substring(i+2,i+4);var byte2Hex=dtcHexString.substring(i,i+2);(0,_logger.log)('debug',`DTCs from position ${i}: swapping ${byte2Hex}${byte1Hex} to ${byte1Hex}${byte2Hex}`);var byte1=(0,_utils.parseHexInt)(byte1Hex);var byte2=(0,_utils.parseHexInt)(byte2Hex);if(isNaN(byte1)||isNaN(byte2))continue;var dtc=this._decodeDTC(byte1.toString(16),byte2.toString(16));if(dtc){var dtcString=this._dtcToString(dtc);if(dtcString){dtcs.add(dtcString);(0,_logger.log)('debug','Found DTC:',dtcString);}}}}return Array.from(dtcs);}}]);}(_BaseDecoder2.BaseDecoder); //# sourceMappingURL=Can.js.map