retropilot-server/cabana/static/js/main.f2e8c285.chunk.js.map

1 line
473 KiB
Plaintext

{"version":3,"sources":["utils/object.js","models/can/BoardUnit.js","utils/css.js","utils/color.js","config.js","utils/dbc.js","utils/url.js","init.js","logging/Sentry.js","CanExplorer.js","api/github-auth.js","logging/CloudLog.js","components/AddSignals.js","models/can/dbc.js","components/Modals/OnboardingModal.js","components/SaveDbcModal.js","components/EditMessageModal.js","components/LoadingBar.js","api/unlogger.js","utils/string.js","retropilotloader.js","utils/array.js","models/graph-data.js","vega/CanPlot.js","components/CanGraph.js","components/CanGraphList.js","components/HLS.js","components/PlayButton.js","components/RouteSeeker/RouteSeeker.js","components/RouteVideoSync.js","components/CanLog.js","models/can/entries.js","components/PlaySpeedSelector.js","components/Explorer.js","components/SignalLegendEntry/FIELDS.js","components/SignalLegendEntry/Field.js","components/SignalLegendEntry/SignalForm.js","components/SignalLegendEntry/NumberField.js","components/SignalLegendEntry/OptionField.js","components/SignalLegendEntry/StringField.js","components/SignalLegendEntry/ColorBar.js","components/SignalLegendEntry/index.js","components/SignalLegend.js","components/GithubDbcList.js","components/DbcUpload.js","components/LoadDbcModal.js","components/MessageBytes.js","components/Meta.js","index.js","api/localstorage.js","utils/debounce.js","models/can/signal.js","components/Modals/baseModal.js","images/webusb-enable-experimental-features.png","images/webusb-enable-webusb.png","workers/rlog-downloader.worker.js","workers/dbc-csv-downloader.worker.js","workers/message-parser.worker.js","workers/CanStreamerWorker.worker.js","acura-dbc.js","api/OpenDbc.js","models/can/frame.js","demo.js","logging/LogEntries.js","corolla-dbc.js","models/can/logSignals.js"],"names":["swapKeysAndValues","obj","f","Object","keys","reduce","acc","k","BoardUnit","name","this","attributes","comment","styles","classes","forEach","call","arguments","it","_definition","_name","push","classNames","apply","css","shade","opacity","r","g","b","t","opacityPos","Math","abs","round","GITHUB_CLIENT_ID","GITHUB_REDIRECT_URL","GITHUB_AUTH_TOKEN_KEY","OPENDBC_SOURCE_REPO","USE_UNLOGGER","window","getUrlParameter","UNLOGGER_HOST","LOGENTRIES_TOKEN","PART_SEGMENT_LENGTH","CAN_GRAPH_MAX_POINTS","STREAMING_WINDOW","EXPLORER_URL","createMessageSpec","dbc","address","id","bus","frame","getMessageFrame","size","entries","byteColors","Array","fill","byteStateChangeCounts","determineByteStateChangeTimes","hexData","time","msgSize","lastParsedMessage","byteStateChangeTimes","i","length","substr","createMessageEntry","relTime","data","signals","getSignalValues","Buffer","from","toString","updated","Date","now","parseMessage","timeStart","msgSpec","msgEntry","BIG_ENDIAN_START_BITS","j","bigEndianBitIndex","matrixBitIndex","indexOf","addCanMessage","canMessage","canStartTime","messages","prevMsgEntries","byteStateChangeCountsByMessage","busTime","undefined","prevMsgEntry","every","c","map","count","idx","matrixBitNumber","bigEndianIndex","reparseMessage","msg","findMaxByteStateChangeCount","values","m","counts","countArr","concat","count1","count2","setMessageByteColors","message","maxByteStateChangeCount","isNaN","min","red","objToQuery","encodeURIComponent","decodeURIComponent","join","location","replace","results","RegExp","exec","search","modifyQueryParameters","add","remove","params","key","value","origin","pathname","init","Sentry","routeFullName","isDemo","segments","split","Number","props","autoplay","startTime","persistedDbc","dongleId","route","fetchPersistedDbc","max","url","exp","sig","isLegacyShare","isShare","demoProps","dbcFilename","authTokenQueryParam","githubAuthToken","persistGithubAuthToken","urlNoAuthToken","href","fetchPersistedGithubAuthToken","a","CommaAuth","token","loadRetropilotDrive","global","retropilotLoaded","retropilotProps","Request","configure","ReactDOM","render","document","getElementById","renderDom","opts","__webpack_hash__","release","Raven","config","install","RLogDownloader","require","LogCSVDownloader","MessageParser","CanStreamerWorker","dataCache","CanExplorer","partChangeDebounced","debounce","loadMessagesFromCache","spawnWorker","state","thumbnails","selectedMessages","canFrameOffset","routeInitTime","firstFrameTime","firstCanTime","lastBusTime","selectedMessage","currentParts","currentPart","currentWorkers","loadingParts","loadedParts","showOnboarding","showLoadDbc","showSaveDbc","showEditMessageModal","editMessageModalMessage","DBC","dbcText","text","dbcLastSaved","seekTime","seekIndex","isLoading","partsLoaded","spawnWorkerHash","attemptingPandaConnection","pandaNoDeviceSelected","live","isGithubAuthenticated","shareUrl","logUrls","openDbcClient","OpenDbc","unloggerClient","UnloggerClient","bind","hideOnboarding","hideLoadDbc","hideSaveDbc","hideEditMessageModal","onDbcSelected","onDbcSaved","onConfirmedSignalChange","onPartChange","onMessageFrameEdited","onSeek","onUserSeek","onMessageSelected","onMessageUnselected","initCanData","updateSelectedMessages","handlePandaConnect","processStreamedCanMessages","onStreamedCanMessagesProcessed","showingModal","lastMessageEntriesById","githubSignOut","downloadLogAsCSV","pandaReader","Panda","onMessage","dataCacheTimer","interval","loadMessagesFromCacheRunning","part","lastUsed","console","log","filter","p","setState","isAuthenticated","retropilotLogUrls","demoLogUrls","retropilotRoute","demoRoute","Moment","fullname","proclog","start_time","urlPromise","logUrlsPromise","routeName","Promise","resolve","DrivesApi","getRouteInfo","then","RawDataApi","getLogUrls","all","initData","newState","getShareSignature","shareSignature","catch","err","error","lastUpdated","persistDbc","writer","createWriteStream","getWriter","encoder","TextEncoder","downloadLiveLogAsCSV","dataHandler","downloadRawLogAsCSV","e","logData","shouldClose","progress","close","uint8array","encode","write","handler","worker","onmessage","postMessage","sourceId","source","slice","newThumbnails","oldIndex","newIndex","monoTime","result","workerHash","options","minPart","maxPart","allWorkerParts","partOffset","tempPart","hash","random","newMessages","isFinished","addMessagesToDataCache","prepend","dataCallback","base","num","msgEntries","newMsgEntries","msgLength","newMsgLength","entryLength","msgIndex","newMsgIndex","DbcUtils","getParseSegment","entry","parseMessageEntry","addAndRehydrateMessages","msgs","lastEntry","loadMessagesFromCacheTimer","timeout","isCanceled","start","performance","promises","l","prev","cacheEntry","newMessageEntries","messageEntries","promise","getParseSegmentInternal","reparseMessages","end","warn","messageId","_messages","reject","_entry","lastMsg","memo","val","showAddSignal","setSignals","updateMessageFrame","decacheMessageId","msgKey","createFrame","messageFrame","set","seek","findIndex","GithubAuth","className","msgId","newCanMessages","canStreamerWorker","windowFloor","messageIds","newEntryFloor","firstEntryIndexInsideStreamingWindow","enforceStreamingMessageWindow","_onStreamedCanMessagesProcessed","unlisten","onError","stack","dataArray","unpersistGithubAuthToken","preventDefault","cx","onClick","loginWithGithub","saveLog","startSegments","selectedPart","routeStartTime","videoOffset","partsCount","routes","handleClose","sourceDbcFilename","hasGithubAuth","handleSave","Component","authorizeUrl","client_id","redirect_uri","scope","JSON","stringify","CloudLog","LogEntries","no_format","catchall","context","update","level","__JEST__","ctx","created","getTime","src","emit","Styles","StyleSheet","create","bit","margin","padding","userSelect","cursor","textAlign","position","bitSelectedStyle","backgroundColor","bitSignificance","fontSize","display","bottom","left","right","highlightedSignalTitle","AddSignals","updateSignalStyles","signalStyles","calcSignalStyles","onSignalHover","signal","highlightedSignal","onBitHover","bitIdx","dragStartBit","dragSignal","copySignals","assign","startBit","isLittleEndian","msbBitIndex","lsbBitNumber","diff","bitDescription","floor","lsbBitIndex","dragCurrentBit","onSignalHoverEnd","resetDragState","onTentativeSignalChange","onSignalChange","oldSignal","signalName","uid","propagateUpSignalChange","onSignalRemove","onSignalPlotChange","shouldPlot","signalUid","bits","signalsCopy","nextProps","nextState","messageIndex","plottedSignalUids","colorRgbStr","colors","getColors","selectedMessageKey","darkenedColors","lightenedColors","colorsCommaSep","color","signalColorStyle","newProps","existingNames","signalNum","Signal","nextNewSignalName","dragEndBit","signalForBit","isDragAcrossSingleByte","createSignal","createSignalIfNotExtendingOne","byteIdx","byteBitIdx","readInt8","bigEndianStartBit","bigEndianCurrentBit","bigEndianBitIdx","rowCount","rows","rowBits","bitStyle","bitDesc","isMsb","isLsb","bitIsContainedInSelection","bitValue","onMouseEnter","onMouseLeave","onMouseDown","onBitMouseDown","onMouseUp","onBitMouseUp","onDoubleClick","onBitDoubleClick","byteValueHex","cellSpacing","toFixed","isLogEvent","renderBitMatrix","UINT64","DBC_COMMENT_RE","DBC_COMMENT_MULTI_LINE_RE","MSG_RE","SIGNAL_RE","MP_SIGNAL_RE","VAL_RE","VAL_TABLE_RE","MSG_TRANSMITTER_RE","SIGNAL_COMMENT_RE","SIGNAL_COMMENT_MULTI_LINE_RE","MESSAGE_COMMENT_RE","MESSAGE_COMMENT_MULTI_LINE_RE","BOARD_UNIT_RE","BOARD_UNIT_COMMENT_RE","BOARD_UNIT_COMMENT_MULTI_LINE_RE","floatOrInt","numericStr","isInteger","parseInt","parseFloat","dbcString","boardUnits","comments","Map","importDbcString","LogSignals","get","messageNames","msgName","msgNum","boardUnitNames","bu","missingBoardUnits","arr","receiver","receivers","recv","array","updateBoardUnits","txt","_newSymbols","boardUnitsText","frames","messageTxs","transmitters","addr","txs","signalsByMsgId","s1","s2","msgAddr","valueDescriptions","valueDescriptionText","trim","Frame","nextNewFrameName","newMsg","warnings","valueTables","followUp","lines","line","type","followUpLine","partialComment","matches","match","idString","transmitter","isSigned","factor","offset","unit","receiverStr","signalProperties","s","vals","description","table","tableName","items","hasFollowUp","newBoardUnits","boardUnitName","boardUnit","find","signalSpec","dataBitPos","blen","swapOrder","wordSize","gSize","swappedWords","word","rightHandAnd","pow","ival","shiftr","and","toNumber","buf","shiftAmount","signalValue","bitPos","byteOffset","readUInt32LE","readUInt32BE","has","buffer","paddedBuffer","paddedDataHex","rightPad","signalValuesByName","valueForInt64Signal","valueForInt32Signal","metricComment","metric","metrics","metricName","OnboardingModal","webUsbEnabled","navigator","usb","viewingUsbInstructions","pandaConnected","attemptPandaConnection","toggleUsbInstructions","navigateToExplorer","drive","can","renderLogin","renderPandaEligibility","alt","instructionalImages","step2","step3","renderUsbInstructions","renderOnboardingOptions","target","rel","title","subtitle","footer","renderModalFooter","disableClose","variations","renderModalContent","SaveDbcModal","tab","openDbcFork","tabs","commitMessage","commitToGitHub","downloadDbcFile","forkOpenDbcAndWait","renderForkButton","renderTabNavigation","renderActions","getUserOpenDbcFork","filename","commitFile","blob","Blob","FileSaver","saveAs","fork","isTimedOut","setTimeout","setInterval","clearInterval","clearTimeout","content","disabled","data-extension","htmlFor","onChange","renderForkStep","renderFilenameField","renderCommitMessage","navigation","actions","renderTabContent","EditMessageModal","copy","editTransmitter","addTransmitter","keyframes","styled","socket","SocketIO","baseTime","seekSeconds","str","charCodeAt","retropilotHost","driveIdentifier","fetch","response","json","retropilotDrive","alert","status","dbcObj","CorollaDBC","driveUrl","elementWiseEquals","arr1","arr2","ele","findIndexRight","condition","_calcGraphData","samples","skip","x","y","appendNewGraphData","plottedSignals","graphData","plottedMessages","plottedMessageIds","index","maxGraphTime","series","some","signalUidsByMessageId","graphDataMaxMessageTimes","signalUids","maxIndex","ArrayUtils","newGraphData","firstNewEntryIdx","newEntries","signalGraphData","messageIdOutOfBounds","graphDataLowerBound","signalColors","v","DefaultPlotInnerStyle","top","CanGraph","updateBounds","view","bounds","width","run","insertData","changeset","insert","change","plotInnerStyle","shiftX","shiftY","isDataInserted","getGraphData","spec","getGraphSpec","onNewView","onSignalClickTime","onSignalSegment","onDragAnchorMouseDown","onDragAnchorMouseUp","onDragStart","onPlotResize","firstRelTime","lastRelTime","messageRelTime","GraphData","CanPlotSpec","scales","domainMin","segment","domainMax","newSegment","prevProps","canReceiveGraphDrop","dragPos","runAfter","updateStyleFromDragPos","plottedSignal","segmentIsNew","currentTime","runAsync","oldProps","oldState","clickTime","onRelativeTimeClick","isArray","onSegmentChanged","getState","subcontext","brush","rect","container","getBoundingClientRect","clientX","clientY","persist","plotInnerStyleFromMouseEvent","onDragEnd","canReceiveDropClass","ref","onGraphRefAvailable","style","messageName","unplot","background","onResize","measureRef","Vega","logLevel","signalListeners","renderer","emptyTable","CanGraphList","draggingSignal","dragShift","graphToReceiveDrop","plotListRef","plotRefs","renderSignalPlot","onPlotListRefReady","onGraphDragStart","onGraphDragEnd","onMouseMove","draggingGraph","determineDraggingGraph","hidden","elementFromPoint","closestPlot","closest","closestPlotRef","isEqualNode","mergePlots","fromPlot","toPlot","isDragging","addCanGraphRef","onSignalUnplotPressed","onGraphTimeClick","HLS","onSeeking","playing","onLoadStart","onPlaySeek","videoElement","shouldInitVideoTime","onSeeked","onLoadEnd","playbackRate","playbackSpeed","loadSource","paused","play","pause","player","Hls","enableWorker","disablePtsDtsCorrectionInMp4Remux","on","Events","ERROR","event","fatal","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","destroy","attachMedia","onVideoElementAvailable","video","autoPlay","muted","onWaiting","onPlaying","PlayButton","hover","isPlaying","process","onPause","onPlay","imageSource","onMouseOver","RouteSeeker","updateDraggingSeek","ratio","seekedBarStyle","zeroSeekedBarStyle","markerStyle","hiddenMarkerStyle","tooltipStyle","hiddenTooltipStyle","tooltipTime","executePlayTimer","segmentIndices","videoLength","newRatio","updateSeekedBar","nearestFrameTime","segmentProgress","cancelAnimationFrame","playTimer","progressBar","offsetWidth","markerOffsetPct","mouseEventXOffsetPercent","markerWidth","tooltipWidth","ratioTime","requestAnimationFrame","duration","roundTime","loadingOverlay","height","justifyContent","alignItems","zIndex","loadingSpinner","img","hls","seekBar","RouteVideoSync","shouldShowJpeg","videoApi","VideoApi","getQcameraStreamIndex","getQcameraStreamIndexUrl","getRearCameraStreamIndexUrl","userSeekTime","funcSeekToRatio","btoa","String","fromCharCode","playSpeed","onVideoClick","nearestFrameUrl","CanLog","expandedMessages","messageHeights","allPacketsExpanded","renderLogListItemMessage","addDisplayedMessages","renderLogListItem","renderLogList","onExpandAllChanged","toggleExpandAllPackets","toggleSignalPlot","curMessageLength","nextMessageLength","newLength","ITEMS_PER_PAGE","msgIdx","onMessageExpanded","expMsgTime","plot","isFloat","plotted","onSignalPlotPressed","msgIsExpanded","isMessageExpanded","msgHasSignals","isPlotted","isSignalPlotted","plottedButtonClass","plottedButtonText","signalValuePretty","hasSignalsClass","expandedClass","toggleExpandPacketSignals","renderLogListItemSignals","checked","expandAllText","expandAllClass","itemRenderer","itemsRenderer","listLength","pageSize","updateWhenThisValueChanges","findTimeIndex","findRelativeTimeIndex","findSegmentIndices","isRelative","segmentTimeLow","segmentTimeHi","timeIndexFunc","segmentIdxLow","upperSegmentIdxHi","segmentIdxHi","PlaySpeedSelector","onPlaySpeedChanged","currentTarget","float","clipSegment","_segment","_segmentIndices","nextMessage","segmentStartIdx","segmentEndIdx","segmentStartTime","segmentEndTime","Explorer","updateSegment","Entries","userSeekIndex","shouldShowAddSignal","onKeyDown","toggleShouldShowAddSignal","changePlaySpeed","addEventListener","removeEventListener","keyCode","resetSegment","curMessage","messageExists","signalExists","nextSeekMsgEntry","partStartOffset","partEndOffset","windowStartTime","clone","format","windowEndTime","newPlottedSignals","indexFromSeekTime","selectedMessageName","onClose","selectedMessagePlottedSignalUids","fromPlotIdx","splice","toPlotIdx","signalsExpandedClass","graphSegment","renderExplorerSignals","renderSelectMessagePrompt","unsignedTransformation","field","transform","optionValues","Little","Big","startByte","endByte","Signed","Unsigned","Field","children","FieldMap","number","valueCol","fieldSpec","isExpanded","signalEdited","updateField","option","valueOptions","optionEles","opt","defaultValue","string","getSignalEdited","FIELDS","Node","isHighlighted","rgb","SignalLegendEntry","signalCopy","toggleEditing","fieldSpecForName","toggleExpandSignal","stopPropagation","equals","expandedEntryClass","ColorBar","SignalForm","SignalLegend","expandedSignals","includes","updatedExpandedSignals","signalRows","sort","signal1","signal2","checkExpandedSignal","row","GithubDbcList","paths","selectedPath","pathQuery","updatePathQuery","repo","list","path","getDbcContents","dbcContents","onDbcLoaded","placeholder","selectPath","DbcUpload","onTextChanged","LoadDbcModal","dbcSource","userOpenDbcRepo","hasAuth","MessageBytes","isVisible","lastMessageIndex","lastSeekTime","onVisibilityChange","onCanvasRefAvailable","nextLastEntry","curLastEntry","frameForTime","updateCanvas","mostRecentMessageIndex","canvas","mostRecentMsg","findMostRecentMessage","getContext","fillStyle","fillRect","font","fillText","devicePixelRatio","scale","ckmeans","Meta","onFilterChanged","onFilterFocus","onFilterUnfocus","canMsgFilter","logEventMsgFilter","renderMessageBytes","toggleShowLogEvents","filterText","lastSaved","fromNow","hoveredMessages","orderedMessageKeys","showLogEvents","lastSavedTimer","nextMsgKeys","sortMessages","byteCountsDidUpdate","prevMessages","nextMessages","messagesByEntryCount","partialMapping","entryCountKey","entryCounts","bin","entryCount","partial","msg1","msg2","reverse","toLowerCase","selectedMessageClass","colSpan","orderedMessages","cellPadding","renderLogEventMessages","renderCanMessages","ReadableStream","WritableStream","lastSavedPretty","saveable","data-clipboard-text","data-clipboard-action","Clipboard","onFocus","onBlur","renderAvailableMessagesList","maybeDbc","localStorage","getItem","parse","dbcJson","setItem","GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY","removeItem","func","wait","immediate","args","later","callNow","multiplex","calculateMin","calculateMax","generateColors","_colors","defineProperty","enumberable","byteOrder","signedChar","desc","bitIndex","bitRange","bitNumber","range","littleEndianBitDescription","bigEndianBitDescription","rawRange","rawMin","calculateRawRange","rawMax","parts","lastColor","randomcolor","otherSignal","Modal","windowHeight","modalHeight","updateHeights","contentRect","innerHeight","variation","readVariationClasses","checkClosability","checkYScrollability","module","exports","Worker","OpenDBC","github","GitHub","sourceRepo","getRepo","githubUsername","fetchGithubUsername","getUser","user","getProfile","profile","login","repoFullName","username","repoName","getContents","dbcPath","fileContents","rawContentsUrl","download_url","cache","resp","repoDetails","full_name","getGithubUsername","getDetails","repoDetailResp","repoSourceIsOpenDbc","contents","getRef","refResp","getCommit","object","sha","headCommitResp","headCommit","getTree","tree","headTreeResp","headTree","mode","createTree","createTreeResp","createdTree","commit","commitResp","updateHead","updateHeadResp","extended","txName","txNum","nextNewTransmitterName","header","self","_indexOf","_getAjaxObject","XDomainRequest","XMLHttpRequest","LogStream","_endpoint","_traceCode","trace","PI","substring","_pageInfo","page_info","_token","_print","print","_noFormat","_SSL","ssl","protocol","LEENDPOINT","_backlog","_active","_sentPageInfo","_apiCall","request","constructor","onreadystatechange","readyState","shift","onload","open","setRequestHeader","overrideMimeType","send","_getEvent","prototype","Error","_agentInfo","nav","doNotTrack","screen","referrer","innerWidth","browser","appName","version","appVersion","cookie_enabled","cookieEnabled","do_not_track","platform","_rawLog","serialized","ex","oldHandler","onerror","newHandler","Logger","logger","dict","endpoint","_log","info","loggers","_createLogStream","hasOwnProperty","_deprecatedInit","createLogStream","to","_getLogger","_destroyLogStream","signalMap","FrontLeftWheel","shortSignal","FrontRightWheel","RearLeftWheel","RearRightWheel","VEgo","AEgo","VEgoRaw","YawRate","SteeringAngle","longSignal","Brake","Gas","LeftBlinker","boolSignal","RightBlinker","GenericToggle","DoorOpen","SeatbeltUnlatched","GasPressed","BrakeLights","SteeringPressed","Standstill","GearShifter","unsigned","charSignal","RcvTow","GpsWeek","LeapSeconds","NumMeas","Voltage","Current","Started","ControlsAllowed","GasInterceptorDetected","StartedSignalDetected","Cpu0","Cpu1","Cpu2","Cpu3","Mem","Gpu","FanSpeed","BatteryPercent","UsbOnline","FreeSpace","ADDRESS_LIST","nameForAddress","isLogAddress","frameForAddress","createSignalEntry","addressForName"],"mappings":"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A,wPACA,sPACA,0PACA,wPACA,sPACA,sPACA,sPACA,0PACA,sPACA,0PACA,0PACA,sPACA,sPACA,wPACA,sPACA,wPACA,sPACA,sPACA,0PACA,sPACA,sPACA,sPACA,sPACA,sPACA,0PACA,sPACA,0PACA,wPACA,0PACA,sPACA,wPACA,sPACA,0PACA,sPACA,wPACA,wPACA,wPACA,sPACA,wPACA,sPACA,wPACA,sPACA,sPACA,4PACA,sPACA,sPACA,wPACA,sPACA,wPACA,0PACA,wPACA,sPACA,wPACA,0PACA,sPACA,sPACA,8PACA,sPACA,0PACA,wPACA,sPACA,wPACA,wPACA,wPACA,sPACA,0PACA,wPACA,sPACA,0PACA,sPACA,wPACA,sPACA,sPACA,sPACA,sPACA,sPACA,wPACA,0PACA,wPACA,sPACA,sPACA,wPACA,sPACA,sPACA,uPACA,yPACA,uPACA,uPACA,uPACA,yPACA,uPACA,uPACA,uPACA,yPACA,yPACA,uPACA,yPACA,uPACA,yPACA,uPACA,uPACA,uPACA,uPACA,2PACA,wPAGWnH,EAAY,CACvBN,IAAKyH,EAAY/M,OACjB3D,KAAM,uBACN8I,SAAU,mBACVtG,IAAKisB,IACLnmB,QAAQ,EACRkB,YAAa,iCAGFoH,EAAY,CACvBE,SAAU,wCACVC,QAASxH,EAAUN,IACnB+H,WAAYH,IAAOtH,EAAUvJ,KAAM,qBACnCkJ,IAAK,iJ,gCCzIP,GAAsB,qBAAXnH,EAET,IAAIA,EAASywC,KAEf,IAAIC,EAAW,SAAXA,SAAoBtuB,EAAO3kB,GAC7B,IAAK,IAAIkE,EAAI,EAAGA,EAAIygB,EAAMxgB,OAAQD,IAChC,GAAIlE,IAAQ2kB,EAAMzgB,GAChB,OAAOA,EAGX,OAAQ,GAINgvC,EAAiB,SAAjBA,iBACF,MAA8B,qBAAnBC,eAEF,IAAIA,eAEN,IAAIC,gBAQb,SAASC,UAAU3+B,GAIjB,IAqBI4+B,EArBAC,EAAa7+B,EAAQ8+B,OACpBzxC,KAAKkT,SAAWlT,KAAK0xC,IAAI7uC,SAAS,IAAI8uC,UAAU,EAAG,IACpD,KAEAC,EA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","file":"static/js/main.f2e8c285.chunk.js","sourcesContent":["export function swapKeysAndValues(obj, f) {\n return Object.keys(obj).reduce((acc, k) => {\n acc[obj[k]] = k;\n return acc;\n }, {});\n}\n\nexport function fromArray(arr) {\n // arr is an array of array key-value pairs\n // like [['a', 1], ['b', 2]]\n\n const pairs = arr.map(([k, v]) => ({ [k]: v }));\n if (pairs.length > 0) {\n return Object.assign(...pairs);\n }\n return {};\n}\n","export default class BoardUnit {\n constructor(name) {\n this.name = name;\n this.attributes = {};\n this.comment = null;\n }\n\n text() {\n return this.name;\n }\n}\n","// Wrapper of aphrodite css() function\n// that supports string class names in\n// addition to style objects.\n\n// Useful for component testing\n\nimport { css } from 'aphrodite';\nimport classNames from 'classnames';\n\nexport default function () {\n const styles = [];\n const classes = [];\n\n [].forEach.call(arguments, (it) => {\n if (it && it._definition && it._name) styles.push(it);\n else classes.push(it);\n });\n\n return classNames.apply(null, [...classes, css(styles)]);\n}\n","export function shade([r, g, b], opacity) {\n /*\n @param {Array} rgb\n @param {Number} opacity -1.0 -> +1.0\n negative opacity will darken image\n\n returns new RGB array\n */\n const t = opacity < 0 ? 0 : 255;\n const opacityPos = Math.abs(opacity);\n\n return [\n Math.round((t - r) * opacityPos) + r,\n Math.round((t - g) * opacityPos) + g,\n Math.round((t - b) * opacityPos) + b\n ];\n}\n","import { getUrlParameter } from './utils/url';\n\nconst ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'debug';\n\nconst ENV_GITHUB_CLIENT_ID = {\n debug: 'f1e42d14f45491f9ca34',\n prod: '4b43250e7499a97d62a5'\n};\nexport const GITHUB_CLIENT_ID = ENV_GITHUB_CLIENT_ID[ENV];\n\nconst ENV_GITHUB_REDIRECT_URL = {\n debug: 'http://127.0.0.1:1235/callback',\n prod: 'https://api.comma.ai/cabana/ghcallback'\n};\nexport const GITHUB_REDIRECT_URL = ENV_GITHUB_REDIRECT_URL[ENV];\nexport const GITHUB_AUTH_TOKEN_KEY = 'gh_access_token';\nexport const OPENDBC_SOURCE_REPO = 'commaai/opendbc';\n\nexport const USE_UNLOGGER = typeof window !== 'undefined' && getUrlParameter('unlogger') !== null;\nexport const UNLOGGER_HOST = 'http://localhost:8080/unlogger';\n\nexport const LOGENTRIES_TOKEN = '4bc98019-8277-4fe0-867c-ed21ea843cc5';\n\nexport const PART_SEGMENT_LENGTH = 3;\n\nexport const CAN_GRAPH_MAX_POINTS = 5000;\n\nexport const STREAMING_WINDOW = 60;\n\nconst ENV_EXPLORER_URL = {\n debug: 'http://127.0.0.1:3000/',\n prod: 'https://my.comma.ai/'\n};\nexport const EXPLORER_URL = ENV_EXPLORER_URL[ENV];\n","function findMaxByteStateChangeCount(messages) {\n return Object.values(messages)\n .map((m) => m.byteStateChangeCounts)\n .reduce((counts, countArr) => counts.concat(countArr), []) // flatten arrays\n .reduce((count1, count2) => (count1 > count2 ? count1 : count2), 0); // find max\n}\n\nfunction addCanMessage(\n canMessage,\n dbc,\n canStartTime,\n messages,\n prevMsgEntries,\n byteStateChangeCountsByMessage\n) {\n const {\n address, busTime, data, bus\n } = canMessage;\n const id = `${bus}:${address.toString(16)}`;\n\n if (messages[id] === undefined) messages[id] = createMessageSpec(dbc, address, id, bus);\n\n const prevMsgEntry = messages[id].entries.length > 0\n ? messages[id].entries[messages[id].entries.length - 1]\n : prevMsgEntries[id] || null;\n\n if (\n byteStateChangeCountsByMessage[id]\n && messages[id].byteStateChangeCounts.every((c) => c === 0)\n ) {\n messages[id].byteStateChangeCounts = byteStateChangeCountsByMessage[id];\n }\n\n const { msgEntry, byteStateChangeCounts } = parseMessage(\n dbc,\n busTime,\n address,\n data,\n canStartTime,\n prevMsgEntry\n );\n\n messages[id].byteStateChangeCounts = byteStateChangeCounts.map(\n (count, idx) => messages[id].byteStateChangeCounts[idx] + count\n );\n\n messages[id].entries.push(msgEntry);\n\n return msgEntry;\n}\n\nfunction createMessageSpec(dbc, address, id, bus) {\n const frame = dbc.getMessageFrame(address);\n const size = frame ? frame.size : 8;\n\n return {\n address,\n id,\n bus,\n entries: [],\n frame,\n byteColors: Array(size).fill(0),\n byteStateChangeCounts: Array(size).fill(0)\n };\n}\n\nfunction determineByteStateChangeTimes(\n hexData,\n time,\n msgSize,\n lastParsedMessage\n) {\n const byteStateChangeCounts = Array(msgSize).fill(0);\n let byteStateChangeTimes;\n\n if (!lastParsedMessage) {\n byteStateChangeTimes = Array(msgSize).fill(time);\n } else {\n // debugger;\n byteStateChangeTimes = lastParsedMessage.byteStateChangeTimes;\n\n for (let i = 0; i < byteStateChangeTimes.length; i++) {\n const currentData = hexData.substr(i * 2, 2);\n const prevData = lastParsedMessage.hexData.substr(i * 2, 2);\n\n if (currentData !== prevData) {\n byteStateChangeTimes[i] = time;\n byteStateChangeCounts[i] = 1;\n }\n }\n }\n\n return { byteStateChangeTimes, byteStateChangeCounts };\n}\n\nfunction createMessageEntry(\n dbc,\n address,\n time,\n relTime,\n data,\n byteStateChangeTimes\n) {\n return {\n signals: dbc.getSignalValues(address, data),\n address,\n data,\n time,\n relTime,\n hexData: Buffer.from(data).toString('hex'),\n byteStateChangeTimes,\n updated: Date.now()\n };\n}\n\nfunction reparseMessage(dbc, msg, lastParsedMessage) {\n const msgSpec = dbc.getMessageFrame(msg.address);\n const msgSize = msgSpec ? msgSpec.size : 8;\n\n const {\n byteStateChangeTimes,\n byteStateChangeCounts\n } = determineByteStateChangeTimes(\n msg.hexData,\n msg.relTime,\n msgSize,\n lastParsedMessage\n );\n\n const msgEntry = {\n ...msg,\n signals: dbc.getSignalValues(msg.address, msg.data),\n byteStateChangeTimes,\n updated: Date.now()\n };\n\n return { msgEntry, byteStateChangeCounts };\n}\n\nfunction parseMessage(dbc, time, address, data, timeStart, lastParsedMessage) {\n let hexData;\n if (typeof data === 'string') {\n hexData = data;\n data = Buffer.from(data, 'hex');\n } else {\n hexData = Buffer.from(data).toString('hex');\n }\n const msgSpec = dbc.getMessageFrame(address);\n const msgSize = msgSpec ? msgSpec.size : 8;\n const relTime = time - timeStart;\n\n const {\n byteStateChangeTimes,\n byteStateChangeCounts\n } = determineByteStateChangeTimes(\n hexData,\n relTime,\n msgSize,\n lastParsedMessage\n );\n const msgEntry = createMessageEntry(\n dbc,\n address,\n time,\n relTime,\n data,\n byteStateChangeTimes\n );\n\n return { msgEntry, byteStateChangeCounts };\n}\n\nconst BIG_ENDIAN_START_BITS = [];\nfor (let i = 0; i < 64; i += 8) {\n for (let j = 7; j > -1; j--) {\n BIG_ENDIAN_START_BITS.push(i + j);\n }\n}\n\nfunction bigEndianBitIndex(matrixBitIndex) {\n return BIG_ENDIAN_START_BITS.indexOf(matrixBitIndex);\n}\n\nfunction matrixBitNumber(bigEndianIndex) {\n return BIG_ENDIAN_START_BITS[bigEndianIndex];\n}\n\nfunction setMessageByteColors(message, maxByteStateChangeCount) {\n message.byteColors = message.byteStateChangeCounts\n .map((count) => (isNaN(count)\n ? 0\n : Math.min(255, 75 + 180 * (count / maxByteStateChangeCount))))\n .map((red) => `rgb(${Math.round(red)},0,0)`);\n\n return message;\n}\n\nexport default {\n bigEndianBitIndex,\n addCanMessage,\n createMessageSpec,\n matrixBitNumber,\n parseMessage,\n reparseMessage,\n findMaxByteStateChangeCount,\n setMessageByteColors,\n createMessageEntry\n};\n","/* eslint-disable no-restricted-globals */\nexport function objToQuery(obj) {\n return Object.keys(obj)\n .map((k) => `${k}=${encodeURIComponent(decodeURIComponent(obj[k]))}`)\n .join('&');\n}\n\nexport function getUrlParameter(name) {\n const { location } = window;\n name = name.replace(/[[]/, '\\\\[').replace(/[\\]]/, '\\\\]');\n const regex = new RegExp(`[\\\\?&]${name}=([^&#]*)`);\n const results = regex.exec(location.search);\n\n return results === null\n ? null\n : decodeURIComponent(results[1].replace(/\\+/g, ' '));\n}\n\nexport function modifyQueryParameters({ add, remove = [] }) {\n const regex = new RegExp('[\\\\?&]([^&#]+)=([^&#]*)');\n const results = regex.exec(location.search);\n\n let params = {};\n if (results != null) {\n for (let i = 1; i < results.length - 1; i += 2) {\n const key = results[i];\n const value = results[i + 1];\n params[key] = value;\n }\n for (const key in params) {\n if (remove.indexOf(key) !== -1) {\n delete params[key];\n }\n }\n params = { ...params, ...add };\n } else {\n params = add;\n }\n\n return `${location.origin + location.pathname}?${objToQuery(params)}`;\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport CommaAuth from '@commaai/my-comma-auth';\nimport { request as Request } from '@commaai/comma-api';\nimport Sentry from './logging/Sentry';\nimport CanExplorer from './CanExplorer';\nimport AcuraDbc from './acura-dbc';\nimport { getUrlParameter, modifyQueryParameters } from './utils/url';\nimport { GITHUB_AUTH_TOKEN_KEY } from './config';\nimport {\n fetchPersistedDbc,\n fetchPersistedGithubAuthToken,\n persistGithubAuthToken\n} from './api/localstorage';\nimport { demoProps } from './demo';\nimport {loadRetropilotDrive} from './retropilotloader';\n\nexport default function init() {\n Sentry.init();\n\n const routeFullName = getUrlParameter('route');\n const isDemo = !!getUrlParameter('demo');\n let segments = getUrlParameter('segments');\n if (segments && segments.length) {\n segments = segments.split(',').map(Number);\n\n if (segments.length !== 2) {\n segments = undefined;\n }\n }\n\n let props = {\n autoplay: true,\n startTime: Number(getUrlParameter('seekTime') || 0),\n segments,\n isDemo\n };\n let persistedDbc = null;\n\n if (routeFullName) {\n const [dongleId, route] = routeFullName.split('|');\n props.dongleId = dongleId;\n props.name = route;\n\n persistedDbc = fetchPersistedDbc(routeFullName);\n\n const max = getUrlParameter('max');\n const url = getUrlParameter('url');\n const exp = getUrlParameter('exp');\n const sig = getUrlParameter('sig');\n\n if (max) {\n props.max = max;\n }\n if (url) {\n props.url = url;\n }\n if (exp) {\n props.exp = exp;\n }\n if (sig) {\n props.sig = sig;\n }\n props.isLegacyShare = max && url && !exp && !sig;\n props.isShare = max && url && exp && sig;\n } else if (isDemo) {\n props = { ...props, ...demoProps };\n }\n\n if (persistedDbc) {\n const { dbcFilename, dbc } = persistedDbc;\n props.dbc = dbc;\n props.dbcFilename = dbcFilename;\n }\n\n const authTokenQueryParam = getUrlParameter(GITHUB_AUTH_TOKEN_KEY);\n if (authTokenQueryParam !== null) {\n props.githubAuthToken = authTokenQueryParam;\n persistGithubAuthToken(authTokenQueryParam);\n const urlNoAuthToken = modifyQueryParameters({\n remove: [GITHUB_AUTH_TOKEN_KEY]\n });\n window.location.href = urlNoAuthToken;\n } else {\n props.githubAuthToken = fetchPersistedGithubAuthToken();\n }\n\n async function renderDom() {\n const token = await CommaAuth.init();\n \n await loadRetropilotDrive(getUrlParameter('retropilotHost') || '', getUrlParameter('retropilotIdentifier') || '', getUrlParameter('seekTime') || 0);\n if (global.retropilotLoaded) {\n props = global.retropilotProps;\n }\n\n if (token) {\n Request.configure(token);\n }\n ReactDOM.render(<CanExplorer {...props} />, document.getElementById('root')); // eslint-disable-line react/jsx-props-no-spreading\n }\n\n renderDom();\n}\n","import Raven from 'raven-js';\n\nfunction init() {\n if (process.env.NODE_ENV === 'production') {\n const opts = {};\n\n if (typeof __webpack_hash__ !== 'undefined') { // eslint-disable-line camelcase\n opts.release = __webpack_hash__; // eslint-disable-line no-undef, camelcase\n }\n\n Raven.config(\n 'https://50006e5d91894f508dd288bbbf4585a6@sentry.io/185303',\n opts\n ).install();\n }\n}\n\nexport default { init };\n","import React, { Component } from 'react';\nimport Moment from 'moment';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\nimport { createWriteStream } from 'streamsaver';\nimport Panda from '@commaai/pandajs';\nimport CommaAuth from '@commaai/my-comma-auth';\nimport { raw as RawDataApi, drives as DrivesApi } from '@commaai/comma-api';\nimport { timeout, interval } from 'thyming';\nimport {\n USE_UNLOGGER,\n PART_SEGMENT_LENGTH,\n STREAMING_WINDOW,\n GITHUB_AUTH_TOKEN_KEY\n} from './config';\nimport * as GithubAuth from './api/github-auth';\n\nimport DBC from './models/can/dbc';\nimport Meta from './components/Meta';\nimport Explorer from './components/Explorer';\nimport OnboardingModal from './components/Modals/OnboardingModal';\nimport SaveDbcModal from './components/SaveDbcModal';\nimport LoadDbcModal from './components/LoadDbcModal';\nimport debounce from './utils/debounce';\nimport EditMessageModal from './components/EditMessageModal';\nimport LoadingBar from './components/LoadingBar';\nimport {\n persistDbc,\n fetchPersistedDbc,\n unpersistGithubAuthToken\n} from './api/localstorage';\nimport OpenDbc from './api/OpenDbc';\nimport UnloggerClient from './api/unlogger';\nimport * as ObjectUtils from './utils/object';\nimport { hash } from './utils/string';\nimport { modifyQueryParameters } from './utils/url';\nimport DbcUtils from './utils/dbc';\nimport { demoLogUrls, demoRoute } from './demo';\n\nconst RLogDownloader = require('./workers/rlog-downloader.worker');\nconst LogCSVDownloader = require('./workers/dbc-csv-downloader.worker');\nconst MessageParser = require('./workers/message-parser.worker');\nconst CanStreamerWorker = require('./workers/CanStreamerWorker.worker');\n\nconst dataCache = {};\n\n\nexport default class CanExplorer extends Component {\n constructor(props) {\n super(props);\n this.state = {\n messages: {},\n thumbnails: [],\n selectedMessages: [],\n route: null,\n canFrameOffset: 0,\n routeInitTime: 0,\n firstFrameTime: 0,\n firstCanTime: null,\n lastBusTime: null,\n selectedMessage: null,\n currentParts: [0, 0],\n currentPart: 0,\n currentWorkers: {},\n loadingParts: [],\n loadedParts: [],\n showOnboarding: false,\n showLoadDbc: false,\n showSaveDbc: false,\n showEditMessageModal: false,\n editMessageModalMessage: null,\n dbc: props.dbc ? props.dbc : new DBC(),\n dbcText: props.dbc ? props.dbc.text() : new DBC().text(),\n dbcFilename: props.dbcFilename ? props.dbcFilename : 'New_DBC',\n dbcLastSaved: null,\n seekTime: props.seekTime || 0,\n seekIndex: 0,\n maxByteStateChangeCount: 0,\n isLoading: true,\n partsLoaded: 0,\n spawnWorkerHash: null,\n attemptingPandaConnection: false,\n pandaNoDeviceSelected: false,\n live: false,\n isGithubAuthenticated:\n props.githubAuthToken !== null && props.githubAuthToken !== undefined,\n shareUrl: null,\n logUrls: null\n };\n\n this.openDbcClient = new OpenDbc(props.githubAuthToken);\n if (USE_UNLOGGER) {\n this.unloggerClient = new UnloggerClient();\n }\n\n this.showOnboarding = this.showOnboarding.bind(this);\n this.hideOnboarding = this.hideOnboarding.bind(this);\n this.showLoadDbc = this.showLoadDbc.bind(this);\n this.hideLoadDbc = this.hideLoadDbc.bind(this);\n this.showSaveDbc = this.showSaveDbc.bind(this);\n this.hideSaveDbc = this.hideSaveDbc.bind(this);\n this.showEditMessageModal = this.showEditMessageModal.bind(this);\n this.hideEditMessageModal = this.hideEditMessageModal.bind(this);\n this.onDbcSelected = this.onDbcSelected.bind(this);\n this.onDbcSaved = this.onDbcSaved.bind(this);\n this.onConfirmedSignalChange = this.onConfirmedSignalChange.bind(this);\n this.onPartChange = this.onPartChange.bind(this);\n this.onMessageFrameEdited = this.onMessageFrameEdited.bind(this);\n this.onSeek = this.onSeek.bind(this);\n this.onUserSeek = this.onUserSeek.bind(this);\n this.onMessageSelected = this.onMessageSelected.bind(this);\n this.onMessageUnselected = this.onMessageUnselected.bind(this);\n this.initCanData = this.initCanData.bind(this);\n this.updateSelectedMessages = this.updateSelectedMessages.bind(this);\n this.handlePandaConnect = this.handlePandaConnect.bind(this);\n this.processStreamedCanMessages = this.processStreamedCanMessages.bind(\n this\n );\n this.onStreamedCanMessagesProcessed = this.onStreamedCanMessagesProcessed.bind(\n this\n );\n this.showingModal = this.showingModal.bind(this);\n this.lastMessageEntriesById = this.lastMessageEntriesById.bind(this);\n this.githubSignOut = this.githubSignOut.bind(this);\n this.downloadLogAsCSV = this.downloadLogAsCSV.bind(this);\n\n this.pandaReader = new Panda();\n this.pandaReader.onMessage(this.processStreamedCanMessages);\n }\n\n componentDidMount() {\n this.dataCacheTimer = interval(() => {\n const { currentParts } = this.state;\n let { loadedParts } = this.state;\n if (this.loadMessagesFromCacheRunning || loadedParts.length < 4) {\n return;\n }\n loadedParts.forEach((part) => {\n if (part >= currentParts[0] && part <= currentParts[1]) {\n return;\n }\n if (Date.now() - dataCache[part].lastUsed > 3 * 60 * 1000) {\n console.log('Decaching part', part);\n loadedParts = loadedParts.filter((p) => p !== part);\n this.setState({\n loadedParts\n }, () => { delete dataCache[part]; });\n }\n });\n }, 10000);\n\n const { dongleId, name } = this.props;\n if (CommaAuth.isAuthenticated() && !name) {\n this.showOnboarding();\n } else if (this.props.isDemo) {\n // is demo!\n\n const logUrls = global.retropilotLoaded ? global.retropilotLogUrls : demoLogUrls;\n const route = global.retropilotLoaded ? global.retropilotRoute : demoRoute;\n\n this.setState({\n logUrls,\n route,\n currentParts: [0, Math.min(logUrls.length - 1, PART_SEGMENT_LENGTH - 1)],\n currentPart: 0\n }, this.initCanData);\n } else if (\n this.props.max\n && this.props.url\n && !this.props.exp\n && !this.props.sig\n ) {\n // legacy share? maybe dead code\n const { max, url } = this.props;\n const startTime = Moment(name, 'YYYY-MM-DD--H-m-s');\n\n const route = {\n fullname: `${dongleId}|${name}`,\n proclog: max,\n url,\n start_time: startTime\n };\n this.setState(\n {\n route,\n currentParts: [0, Math.min(max, PART_SEGMENT_LENGTH - 1)]\n },\n this.initCanData\n );\n } else if (dongleId && name) {\n const routeName = `${dongleId}|${name}`;\n let urlPromise;\n let logUrlsPromise;\n\n if (this.props.url) {\n urlPromise = Promise.resolve(this.props.url);\n } else {\n urlPromise = DrivesApi.getRouteInfo(routeName).then((route) => route.url);\n }\n\n if (this.props.sig && this.props.exp) {\n logUrlsPromise = RawDataApi.getLogUrls(routeName, {\n sig: this.props.sig,\n exp: this.props.exp\n });\n } else {\n logUrlsPromise = RawDataApi.getLogUrls(routeName);\n }\n Promise.all([urlPromise, logUrlsPromise])\n .then((initData) => {\n const [url, logUrls] = initData;\n const newState = {\n route: {\n fullname: routeName,\n proclog: logUrls.length - 1,\n start_time: Moment(name, 'YYYY-MM-DD--H-m-s'),\n url\n },\n currentParts: [\n 0,\n Math.min(logUrls.length - 1, PART_SEGMENT_LENGTH - 1)\n ],\n logUrls\n };\n this.setState(newState, this.initCanData);\n\n DrivesApi.getShareSignature(routeName).then((shareSignature) => this.setState({\n shareUrl: modifyQueryParameters({\n add: {\n exp: shareSignature.exp,\n sig: shareSignature.sig,\n max: logUrls.length - 1,\n url\n },\n remove: [GITHUB_AUTH_TOKEN_KEY]\n })\n }));\n })\n .catch((err) => {\n console.error(err);\n this.showOnboarding();\n });\n } else {\n this.showOnboarding();\n }\n }\n\n componentWillUnmount() {\n if (this.dataCacheTimer) {\n this.dataCacheTimer();\n }\n }\n\n initCanData() {\n const { route } = this.state;\n\n this.spawnWorker(this.state.currentParts);\n }\n\n onDbcSelected(dbcFilename, dbc) {\n const { route } = this.state;\n this.hideLoadDbc();\n dbc.lastUpdated = Date.now();\n this.persistDbc({ dbcFilename, dbc });\n\n if (route) {\n this.setState(\n {\n dbc,\n dbcFilename,\n dbcText: dbc.text(),\n partsLoaded: 0,\n selectedMessage: null,\n messages: {}\n },\n () => {\n this.loadMessagesFromCache();\n }\n );\n } else {\n this.setState({\n dbc,\n dbcFilename,\n dbcText: dbc.text(),\n messages: {}\n });\n }\n }\n\n onDbcSaved(dbcFilename) {\n const dbcLastSaved = Moment();\n this.setState({ dbcLastSaved, dbcFilename });\n this.hideSaveDbc();\n }\n\n // async downloadDbcFile() {\n // const blob = new Blob([this.props.dbc.text()], {type: \"text/plain;charset=utf-8\"});\n // const filename = this.state.dbcFilename.replace(/\\.dbc/g, '') + '.dbc';\n // FileSaver.saveAs(blob, filename, true);\n // }\n\n downloadLogAsCSV() {\n console.log('downloadLogAsCSV:start');\n const { dbcFilename } = this.state;\n const fileStream = createWriteStream(\n `${dbcFilename.replace(/\\.dbc/g, '-')}${+new Date()}.csv`\n );\n const writer = fileStream.getWriter();\n const encoder = new TextEncoder();\n\n if (this.state.live) {\n return this.downloadLiveLogAsCSV(dataHandler);\n }\n return this.downloadRawLogAsCSV(dataHandler);\n\n function dataHandler(e) {\n const { logData, shouldClose, progress } = e.data;\n if (shouldClose) {\n console.log('downloadLogAsCSV:close');\n writer.close();\n return;\n }\n console.log('CSV export progress:', progress);\n const uint8array = encoder.encode(`${logData}\\n`);\n writer.write(uint8array);\n }\n }\n\n downloadRawLogAsCSV(handler) {\n return this.downloadLiveLogAsCSV(handler);\n }\n\n downloadLiveLogAsCSV(handler) {\n // Trigger processing of in-memory data in worker\n // this method *could* just fetch the data needed for the worked, but\n // eventually this might be in it's own worker instead of the shared one\n const { firstCanTime, canFrameOffset } = this.state;\n const worker = new LogCSVDownloader();\n\n worker.onmessage = handler;\n\n worker.postMessage({\n data: Object.keys(this.state.messages).map((sourceId) => {\n const source = this.state.messages[sourceId];\n return {\n id: source.id,\n bus: source.bus,\n address: source.address,\n entries: source.entries.slice()\n };\n }),\n canStartTime: firstCanTime - canFrameOffset\n });\n }\n\n mergeThumbnails(newThumbnails) {\n const { thumbnails } = this.state;\n if (!newThumbnails || !newThumbnails.length) {\n return thumbnails;\n }\n if (!thumbnails.length) {\n return newThumbnails;\n }\n\n let oldIndex = 0;\n let newIndex = 0;\n\n // is old immediately after new?\n if (newThumbnails[0].monoTime > thumbnails[thumbnails.length - 1]) {\n return thumbnails.concat(newThumbnails);\n }\n // is new immediately after old?\n if (newThumbnails[newThumbnails.length - 1] < thumbnails[0]) {\n return newThumbnails.concat(thumbnails);\n }\n let result = [];\n while (oldIndex < thumbnails.length && newIndex < newThumbnails.length) {\n if (thumbnails[oldIndex].monoTime < newThumbnails[newIndex].monoTime) {\n result.push(thumbnails[oldIndex]);\n oldIndex += 1;\n } else {\n result.push(newThumbnails[newIndex]);\n newIndex += 1;\n }\n }\n if (oldIndex < thumbnails.length) {\n result = result.concat(thumbnails.slice(oldIndex));\n } else if (newIndex < newThumbnails.length) {\n result = result.concat(newThumbnails.slice(newIndex));\n }\n\n return result;\n }\n\n cancelWorker(workerHash) {\n // actually don't...\n return;\n const currentWorkers = { ...this.state.currentWorkers };\n const { worker, part } = currentWorkers[workerHash];\n const loadingParts = this.state.loadingParts.filter((p) => p !== part);\n const loadedParts = this.state.loadedParts.filter((p) => p !== part);\n delete currentWorkers[workerHash];\n\n console.log('Stoping worker', workerHash, 'for part', part);\n worker.postMessage({\n action: 'terminate'\n });\n\n this.setState({\n currentWorkers,\n loadingParts,\n loadedParts\n });\n }\n\n spawnWorker(options) {\n let { currentParts, currentWorkers, loadingParts } = this.state;\n console.log('Checking worker for', currentParts);\n if (!this.state.isLoading) {\n this.setState({ isLoading: true });\n }\n if (loadingParts.length > 1) {\n // only 2 workers at a time pls\n return;\n }\n const [minPart, maxPart] = currentParts;\n\n // updated worker list (post canceling, and this time a copy)\n currentWorkers = { ...this.state.currentWorkers };\n\n const { loadedParts, currentPart } = this.state;\n\n let part = -1;\n const allWorkerParts = loadingParts.concat(loadedParts);\n\n for (let partOffset = 0; partOffset <= maxPart - minPart; ++partOffset) {\n let tempPart = currentPart + partOffset;\n if (tempPart > maxPart) {\n tempPart = minPart + ((tempPart - minPart) % (maxPart - minPart + 1));\n }\n if (allWorkerParts.indexOf(tempPart) === -1) {\n part = tempPart;\n break;\n }\n }\n if (part === -1) {\n console.log('Loading complete');\n this.setState({ isLoading: false });\n return;\n }\n console.log('Starting worker for part', part);\n // options is object of {part, prevMsgEntries, spawnWorkerHash, prepend}\n options = options || {};\n let { prevMsgEntries } = options;\n const prepend = false;\n\n const {\n dbc,\n dbcFilename,\n route,\n firstCanTime,\n canFrameOffset\n } = this.state;\n let { maxByteStateChangeCount } = this.state;\n\n if (!prevMsgEntries) {\n // we have previous messages loaded\n const { messages } = this.state;\n prevMsgEntries = {};\n Object.keys(messages).forEach((key) => {\n const { entries } = messages[key];\n prevMsgEntries[key] = entries[entries.length - 1];\n });\n }\n\n // var worker = new CanFetcher();\n const worker = new RLogDownloader();\n\n const spawnWorkerHash = hash(Math.random().toString(16));\n currentWorkers[spawnWorkerHash] = {\n part,\n worker\n };\n\n loadingParts = [part, ...loadingParts];\n\n this.setState({\n currentWorkers,\n loadingParts\n });\n\n worker.onmessage = (e) => {\n if (this.state.currentWorkers[spawnWorkerHash] === undefined) {\n console.log('Worker was canceled');\n return;\n }\n\n maxByteStateChangeCount = e.data.maxByteStateChangeCount;\n const {\n newMessages,\n newThumbnails,\n isFinished,\n routeInitTime,\n firstFrameTime,\n } = e.data;\n if (maxByteStateChangeCount > this.state.maxByteStateChangeCount) {\n this.setState({ maxByteStateChangeCount });\n } else {\n maxByteStateChangeCount = this.state.maxByteStateChangeCount;\n }\n if (routeInitTime !== this.state.routeInitTime) {\n this.setState({ routeInitTime });\n }\n if (firstFrameTime && firstFrameTime !== this.state.firstFrameTime) {\n this.setState({ firstFrameTime });\n }\n\n this.addMessagesToDataCache(part, newMessages, newThumbnails);\n\n // const messages = this.addAndRehydrateMessages(\n // newMessages,\n // maxByteStateChangeCount\n // );\n // const prevMsgEntries = {};\n // Object.keys(newMessages).forEach((key) => {\n // prevMsgEntries[key] = newMessages[key].entries[newMessages[key].entries.length - 1];\n // });\n\n // const thumbnails = this.mergeThumbnails(newThumbnails);\n\n if (isFinished) {\n const loadingParts = this.state.loadingParts.filter((p) => p !== part);\n const loadedParts = [part, ...this.state.loadedParts];\n\n this.setState(\n {\n partsLoaded: this.state.partsLoaded + 1,\n loadingParts,\n loadedParts\n },\n () => {\n this.spawnWorker({\n prevMsgEntries,\n spawnWorkerHash,\n prepend\n });\n if (window.dataCallback) {\n window.dataCallback();\n window.dataCallback = null;\n }\n }\n );\n }\n };\n\n worker.postMessage({\n // old stuff for reverse compatibility for easier testing\n base: route.url,\n num: part,\n\n // so that we don't try to read metadata about it...\n isDemo: this.props.isDemo,\n isLegacyShare: this.props.isLegacyShare,\n logUrls: this.state.logUrls,\n\n // data that is used\n dbcText: dbc.text(),\n route: route.fullname,\n part,\n canStartTime: firstCanTime != null ? firstCanTime - canFrameOffset : null,\n prevMsgEntries,\n maxByteStateChangeCount\n });\n }\n\n addAndRehydrateMessages(newMessages, options) {\n // Adds new message entries to messages state\n // and \"rehydrates\" ES6 classes (message frame)\n // lost from JSON serialization in webworker data cloning.\n // handles merging the data in correct order\n options = options || {};\n\n const messages = { ...this.state.messages };\n\n Object.keys(newMessages).forEach((key) => {\n // add message\n if (options.replace !== true && key in messages) {\n // should merge here instead of concat\n // assumes messages are always sequential\n const msgEntries = messages[key].entries;\n const newMsgEntries = newMessages[key].entries;\n const msgLength = msgEntries.length;\n const newMsgLength = newMsgEntries.length;\n const entryLength = msgLength + newMsgLength;\n messages[key] = {\n ...messages[key],\n entries: Array(entryLength)\n };\n\n let msgIndex = 0;\n let newMsgIndex = 0;\n\n for (let i = 0; i < entryLength; ++i) {\n if (newMsgIndex >= newMsgLength) {\n messages[key].entries[i] = msgEntries[msgIndex++];\n } else if (msgIndex >= msgLength) {\n messages[key].entries[i] = newMsgEntries[newMsgIndex++];\n } else if (\n msgEntries[msgIndex].relTime <= newMsgEntries[newMsgIndex].relTime\n ) {\n messages[key].entries[i] = msgEntries[msgIndex++];\n } else if (\n msgEntries[msgIndex].relTime >= newMsgEntries[newMsgIndex].relTime\n ) {\n messages[key].entries[i] = newMsgEntries[newMsgIndex++];\n }\n }\n messages[key].byteStateChangeCounts = newMessages[key].byteStateChangeCounts;\n } else {\n messages[key] = newMessages[key];\n messages[key].frame = this.state.dbc.getMessageFrame(\n messages[key].address\n );\n }\n });\n\n const maxByteStateChangeCount = DbcUtils.findMaxByteStateChangeCount(\n messages\n );\n this.setState({\n maxByteStateChangeCount\n });\n\n Object.keys(messages).forEach((key) => {\n // console.log(key);\n messages[key] = DbcUtils.setMessageByteColors(\n messages[key],\n maxByteStateChangeCount\n );\n });\n\n return messages;\n }\n\n async addMessagesToDataCache(part, newMessages, newThumbnails) {\n const { dbc, currentParts } = this.state;\n const entry = await this.getParseSegment(part);\n if (!entry) {\n // first chunk of data returned from this segment\n Object.keys(newMessages).forEach((key) => {\n newMessages[key] = this.parseMessageEntry(newMessages[key], dbc);\n });\n dataCache[part] = {\n messages: newMessages,\n thumbnails: newThumbnails,\n lastUpdated: Date.now(),\n lastUsed: Date.now()\n };\n if (part >= currentParts[0] && part <= currentParts[1]) {\n this.setState({\n messages: this.addAndRehydrateMessages(newMessages)\n });\n }\n return;\n }\n\n entry.lastUsed = Date.now();\n\n // data is always append only, and always per segment\n Object.keys(newMessages).forEach((key) => {\n let msgs = newMessages[key];\n if (!dataCache[part].messages[key]) {\n msgs = this.parseMessageEntry(msgs, dbc);\n dataCache[part].messages[key] = msgs;\n } else {\n let { entries } = dataCache[part].messages[key];\n const lastEntry = entries.length ? entries[entries.length - 1] : null;\n msgs = this.parseMessageEntry(msgs, dbc, lastEntry);\n entries = entries.concat(msgs.entries);\n dataCache[part].messages[key].entries = entries;\n }\n newMessages[key] = msgs;\n });\n dataCache[part].thumbnails = dataCache[part].thumbnails.concat(newThumbnails);\n\n if (part >= currentParts[0] && part <= currentParts[1]) {\n this.setState({\n messages: this.addAndRehydrateMessages(newMessages)\n });\n }\n }\n\n async loadMessagesFromCache() {\n // create a new messages object for state\n if (this.loadMessagesFromCacheRunning) {\n if (!this.loadMessagesFromCacheTimer) {\n this.loadMessagesFromCacheTimer = timeout(() => this.loadMessagesFromCache(), 10);\n }\n return;\n }\n this.loadMessagesFromCacheRunning = true;\n if (this.loadMessagesFromCacheTimer) {\n this.loadMessagesFromCacheTimer();\n this.loadMessagesFromCacheTimer = null;\n }\n const { currentParts, dbc } = this.state;\n const { lastUpdated } = dbc;\n const [minPart, maxPart] = currentParts;\n const messages = {};\n let thumbnails = [];\n let isCanceled = false;\n\n let start = performance.now();\n\n const promises = [];\n\n for (let i = minPart, l = maxPart; i <= l; ++i) {\n promises.push(this.getParseSegment(i));\n }\n await promises.reduce(async (prev, p) => {\n await prev;\n if (isCanceled) {\n return;\n }\n const cacheEntry = await p;\n if (this.state.dbc.lastUpdated !== lastUpdated) {\n if (!isCanceled) {\n isCanceled = true;\n this.loadMessagesFromCacheRunning = false;\n console.log('Canceling!');\n this.loadMessagesFromCache();\n }\n return;\n }\n if (cacheEntry) {\n const newMessages = cacheEntry.messages;\n thumbnails = thumbnails.concat(cacheEntry.thumbnails);\n Object.keys(newMessages).forEach((key) => {\n if (!messages[key]) {\n messages[key] = { ...newMessages[key] };\n } else {\n const newMessageEntries = newMessages[key].entries;\n const messageEntries = messages[key].entries;\n if (newMessageEntries.length\n && newMessageEntries[0].relTime < messageEntries[messageEntries.length - 1].relTime) {\n console.error('Found out of order messages', newMessageEntries[0], messageEntries[messageEntries.length - 1]);\n }\n messages[key].entries = messages[key].entries.concat(newMessages[key].entries);\n }\n });\n }\n console.log('Done with', performance.now() - start);\n start = performance.now();\n }, Promise.resolve());\n\n if (isCanceled) {\n return;\n }\n\n Object.keys(this.state.messages).forEach((key) => {\n if (!messages[key]) {\n messages[key] = this.state.messages[key];\n messages[key].entries = [];\n }\n });\n\n Object.keys(messages).forEach((key) => {\n messages[key].frame = dbc.getMessageFrame(\n messages[key].address\n );\n });\n\n const maxByteStateChangeCount = DbcUtils.findMaxByteStateChangeCount(\n messages\n );\n\n this.setState({\n maxByteStateChangeCount\n });\n\n Object.keys(messages).forEach((key) => {\n // console.log(key);\n messages[key] = DbcUtils.setMessageByteColors(\n messages[key],\n maxByteStateChangeCount\n );\n });\n\n console.log('Done with old messages', performance.now() - start);\n\n this.setState({ messages, thumbnails });\n\n this.loadMessagesFromCacheRunning = false;\n }\n\n async getParseSegment(part) {\n if (!dataCache[part]) {\n return null;\n }\n if (dataCache[part].promise) {\n await dataCache[part].promise;\n }\n dataCache[part].promise = this.getParseSegmentInternal(part);\n\n return dataCache[part].promise;\n }\n\n async getParseSegmentInternal(part) {\n const start = performance.now();\n const { dbc } = this.state;\n if (!dbc.lastUpdated) {\n dbc.lastUpdated = Date.now();\n }\n const { lastUpdated } = dbc;\n let { messages } = dataCache[part];\n\n let reparseMessages = {};\n\n // if (lastUpdated > dataCache[part].lastUpdated) {\n // dataCache[part].lastUpdated = Date.now();\n // return await this.reparseMessages(messages);\n // }\n\n Object.keys(messages).forEach((key) => {\n if (messages[key].lastUpdated >= lastUpdated) {\n return;\n }\n reparseMessages[key] = messages[key];\n });\n\n if (Object.keys(reparseMessages).length) {\n console.log('Reparsing messages!', Object.keys(reparseMessages).length);\n reparseMessages = await this.reparseMessages(reparseMessages);\n }\n\n messages = {\n ...messages,\n ...reparseMessages\n };\n\n dataCache[part].messages = messages;\n\n const end = performance.now();\n if (end - start > 200) {\n // warn about anything over 200ms\n console.warn('getParseSegment took', part, end - start, Object.keys(messages).length);\n }\n\n return dataCache[part];\n }\n\n decacheMessageId(messageId) {\n Object.keys(dataCache).forEach((part) => {\n if (dataCache[part].messages[messageId]) {\n dataCache[part].messages[messageId].lastUpdated = 0;\n }\n });\n }\n\n async reparseMessages(_messages) {\n const messages = _messages;\n const { dbc } = this.state;\n dbc.lastUpdated = dbc.lastUpdated || Date.now();\n\n Object.keys(messages).forEach((key) => {\n messages[key].frame = dbc.getMessageFrame(messages[key].address);\n });\n\n return new Promise((resolve, reject) => {\n const worker = new MessageParser();\n worker.onmessage = (e) => {\n const newMessages = e.data.messages;\n Object.keys(newMessages).forEach((key) => {\n newMessages[key].lastUpdated = dbc.lastUpdated;\n newMessages[key].frame = dbc.getMessageFrame(newMessages[key].address);\n });\n resolve(newMessages);\n };\n\n worker.postMessage({\n messages,\n dbcText: dbc.text(),\n canStartTime: this.state.firstCanTime\n });\n });\n }\n\n parseMessageEntry(_entry, dbc, lastMsg) {\n const entry = _entry;\n dbc.lastUpdated = dbc.lastUpdated || Date.now();\n entry.lastUpdated = dbc.lastUpdated;\n entry.frame = dbc.getMessageFrame(\n entry.address\n );\n\n let prevMsgEntry = lastMsg || null;\n const byteStateChangeCounts = [];\n // entry.messages[id].byteStateChangeCounts = byteStateChangeCounts.map(\n // (count, idx) => entry.messages[id].byteStateChangeCounts[idx] + count\n // );\n entry.entries = entry.entries.map((message) => {\n if (message.hexData) {\n prevMsgEntry = DbcUtils.reparseMessage(dbc, message, prevMsgEntry);\n } else {\n prevMsgEntry = DbcUtils.parseMessage(\n dbc,\n message.time,\n message.address,\n message.data,\n message.timeStart,\n prevMsgEntry\n );\n }\n byteStateChangeCounts.push(prevMsgEntry.byteStateChangeCounts);\n prevMsgEntry = prevMsgEntry.msgEntry;\n return prevMsgEntry;\n });\n entry.byteStateChangeCounts = byteStateChangeCounts.reduce((memo, val) => {\n if (!memo) {\n return val;\n }\n return memo.map((count, idx) => val[idx] + count);\n }, null);\n\n return entry;\n }\n\n showingModal() {\n const {\n showOnboarding,\n showLoadDbc,\n showSaveDbc,\n showAddSignal,\n showEditMessageModal\n } = this.state;\n return (\n showOnboarding\n || showLoadDbc\n || showSaveDbc\n || showAddSignal\n || showEditMessageModal\n );\n }\n\n showOnboarding() {\n this.setState({ showOnboarding: true });\n }\n\n hideOnboarding() {\n this.setState({ showOnboarding: false });\n }\n\n showLoadDbc() {\n this.setState({ showLoadDbc: true });\n }\n\n hideLoadDbc() {\n this.setState({ showLoadDbc: false });\n }\n\n showSaveDbc() {\n this.setState({ showSaveDbc: true });\n }\n\n hideSaveDbc() {\n this.setState({ showSaveDbc: false });\n }\n\n updateMessageFrame(messageId, frame) {\n const { messages } = this.state;\n\n messages[messageId].frame = frame;\n this.setState({ messages });\n }\n\n persistDbc({ dbcFilename, dbc }) {\n const { route } = this.state;\n if (route) {\n persistDbc(route.fullname, { dbcFilename, dbc });\n } else {\n persistDbc('live', { dbcFilename, dbc });\n }\n\n this.loadMessagesFromCache();\n }\n\n onConfirmedSignalChange(message, signals) {\n const { dbc, dbcFilename } = this.state;\n dbc.setSignals(message.address, { ...signals });\n\n this.persistDbc({ dbcFilename, dbc });\n\n this.updateMessageFrame(message.id, dbc.getMessageFrame(message.address));\n\n this.setState({ dbc, dbcText: dbc.text() }, () => {\n this.decacheMessageId(message.id);\n this.loadMessagesFromCache();\n });\n }\n\n partChangeDebounced = debounce(() => {\n this.loadMessagesFromCache();\n\n this.spawnWorker();\n }, 500);\n\n onPartChange(part) {\n let {\n currentParts, currentPart, canFrameOffset, route\n } = this.state;\n if (canFrameOffset === -1 || part === currentPart) {\n return;\n }\n\n // determine new parts to load, whether to prepend or append\n let maxPart = Math.min(route.proclog, part + 1);\n const minPart = Math.max(0, maxPart - PART_SEGMENT_LENGTH + 1);\n if (minPart === 0) {\n maxPart = Math.min(route.proclog, 2);\n }\n const currentPartSpan = currentParts[1] - currentParts[0] + 1;\n\n // update current parts\n currentParts = [minPart, maxPart];\n currentPart = part;\n\n if (\n currentPart !== this.state.currentPart\n || currentParts[0] !== this.state.currentParts[0]\n || currentParts[1] !== this.state.currentParts[1]\n ) {\n // update state then load new parts\n this.setState({ currentParts, currentPart }, this.partChangeDebounced);\n }\n }\n\n showEditMessageModal(msgKey) {\n const msg = this.state.messages[msgKey];\n if (!msg.frame) {\n msg.frame = this.state.dbc.createFrame(msg.address);\n }\n\n this.setState({\n showEditMessageModal: true,\n editMessageModalMessage: msgKey,\n messages: this.state.messages,\n dbcText: this.state.dbc.text()\n });\n }\n\n hideEditMessageModal() {\n this.setState({ showEditMessageModal: false });\n }\n\n onMessageFrameEdited(messageFrame) {\n const {\n messages, dbcFilename, dbc, editMessageModalMessage\n } = this.state;\n\n const message = { ...messages[editMessageModalMessage] };\n message.frame = messageFrame;\n dbc.messages.set(messageFrame.id, messageFrame);\n this.persistDbc({ dbcFilename, dbc });\n\n messages[editMessageModalMessage] = message;\n this.setState({ messages, dbc, dbcText: dbc.text() });\n this.hideEditMessageModal();\n }\n\n onSeek(seekIndex, seekTime) {\n this.setState({ seekIndex, seekTime });\n\n const { currentPart } = this.state;\n const part = ~~(seekTime / 60);\n if (part !== currentPart) {\n this.onPartChange(part);\n }\n }\n\n onUserSeek(seekTime) {\n if (USE_UNLOGGER) {\n this.unloggerClient.seek(this.props.dongleId, this.props.name, seekTime);\n }\n\n const msg = this.state.messages[this.state.selectedMessage];\n let seekIndex;\n if (msg) {\n seekIndex = msg.entries.findIndex((e) => e.relTime >= seekTime);\n if (seekIndex === -1) {\n seekIndex = 0;\n }\n } else {\n seekIndex = 0;\n }\n\n this.onSeek(seekIndex, seekTime);\n }\n\n onMessageSelected(msgKey) {\n let { seekTime, seekIndex, messages } = this.state;\n const msg = messages[msgKey];\n\n if (seekTime > 0 && msg.entries.length > 0) {\n seekIndex = msg.entries.findIndex((e) => e.relTime >= seekTime);\n if (seekIndex === -1) {\n seekIndex = 0;\n }\n\n seekTime = msg.entries[seekIndex].relTime;\n }\n\n this.setState({ seekTime, seekIndex, selectedMessage: msgKey });\n }\n\n updateSelectedMessages(selectedMessages) {\n this.setState({ selectedMessages });\n }\n\n onMessageUnselected(msgKey) {\n this.setState({ selectedMessage: null });\n }\n\n loginWithGithub() {\n const { route } = this.state;\n return (\n <a\n href={GithubAuth.authorizeUrl(\n route && route.fullname ? route.fullname : ''\n )}\n className=\"button button--dark button--inline\"\n >\n <i className=\"fa fa-github\" />\n <span> Log in with Github</span>\n </a>\n );\n }\n\n lastMessageEntriesById(obj, [msgId, message]) {\n obj[msgId] = message.entries[message.entries.length - 1];\n return obj;\n }\n\n processStreamedCanMessages(newCanMessages) {\n const { dbcText } = this.state;\n const {\n firstCanTime,\n lastBusTime,\n messages,\n maxByteStateChangeCount\n } = this.state;\n // map msg id to arrays\n const prevMsgEntries = Object.entries(messages).reduce(\n this.lastMessageEntriesById,\n {}\n );\n\n const byteStateChangeCountsByMessage = Object.entries(messages).reduce(\n (obj, [msgId, msg]) => {\n obj[msgId] = msg.byteStateChangeCounts;\n return obj;\n },\n {}\n );\n\n this.canStreamerWorker.postMessage({\n newCanMessages,\n prevMsgEntries,\n firstCanTime,\n dbcText,\n lastBusTime,\n byteStateChangeCountsByMessage,\n maxByteStateChangeCount\n });\n }\n\n firstEntryIndexInsideStreamingWindow(entries) {\n const lastEntryTime = entries[entries.length - 1].relTime;\n const windowFloor = lastEntryTime - STREAMING_WINDOW;\n\n for (let i = 0; i < entries.length; i++) {\n if (entries[i].relTime > windowFloor) {\n return i;\n }\n }\n\n return 0;\n }\n\n enforceStreamingMessageWindow(messages) {\n const messageIds = Object.keys(messages);\n for (let i = 0; i < messageIds.length; i++) {\n const messageId = messageIds[i];\n const message = messages[messageId];\n if (message.entries.length < 2) {\n continue;\n }\n\n const lastEntryTime = message.entries[message.entries.length - 1].relTime;\n const entrySpan = lastEntryTime - message.entries[0].relTime;\n if (entrySpan > STREAMING_WINDOW) {\n const newEntryFloor = this.firstEntryIndexInsideStreamingWindow(\n message.entries\n );\n message.entries = message.entries.slice(newEntryFloor);\n messages[messageId] = message;\n }\n }\n\n return messages;\n }\n\n _onStreamedCanMessagesProcessed(data) {\n let {\n newMessages,\n seekTime,\n lastBusTime,\n firstCanTime,\n maxByteStateChangeCount\n } = data;\n\n if (maxByteStateChangeCount < this.state.maxByteStateChangeCount) {\n maxByteStateChangeCount = this.state.maxByteStateChangeCount;\n }\n\n let messages = this.addAndRehydrateMessages(newMessages);\n messages = this.enforceStreamingMessageWindow(messages);\n let { seekIndex, selectedMessages } = this.state;\n if (\n selectedMessages.length > 0\n && messages[selectedMessages[0]] !== undefined\n ) {\n seekIndex = Math.max(0, messages[selectedMessages[0]].entries.length - 1);\n }\n this.setState({\n messages,\n seekTime,\n seekIndex,\n lastBusTime,\n firstCanTime,\n maxByteStateChangeCount\n });\n }\n\n onStreamedCanMessagesProcessed(e) {\n this._onStreamedCanMessagesProcessed(e.data);\n }\n\n async handlePandaConnect(e) {\n this.setState({ attemptingPandaConnection: true, live: true });\n\n const persistedDbc = fetchPersistedDbc('live');\n if (persistedDbc) {\n const { dbc, dbcText } = persistedDbc;\n this.setState({ dbc, dbcText });\n }\n this.canStreamerWorker = new CanStreamerWorker();\n this.canStreamerWorker.onmessage = this.onStreamedCanMessagesProcessed;\n\n // if any errors go off during connection, mark as not trying to connect anymore...\n const unlisten = this.pandaReader.onError((err) => {\n console.error(err.stack || err);\n this.setState({ attemptingPandaConnection: false });\n });\n try {\n await this.pandaReader.start();\n this.setState({\n showOnboarding: false,\n showLoadDbc: true\n });\n } catch (e) {}\n this.setState({ attemptingPandaConnection: false });\n unlisten();\n }\n\n githubSignOut(e, dataArray) {\n unpersistGithubAuthToken();\n this.setState({ isGithubAuthenticated: false });\n\n e.preventDefault();\n }\n\n render() {\n const {\n route,\n messages,\n selectedMessages,\n currentParts,\n dbcFilename,\n dbcLastSaved,\n seekTime,\n seekIndex,\n shareUrl,\n maxByteStateChangeCount,\n live,\n thumbnails,\n selectedMessage,\n canFrameOffset,\n firstCanTime,\n currentPart,\n partsLoaded\n } = this.state;\n\n const { startTime, segments } = this.props;\n\n return (\n <div\n id=\"cabana\"\n className={cx({ 'is-showing-modal': this.showingModal() })}\n >\n {this.state.isLoading ? (\n <LoadingBar isLoading={this.state.isLoading} />\n ) : null}\n <div className=\"cabana-header\">\n <a className=\"cabana-header-logo\" href=\"\">\n Comma Cabana\n </a>\n <div className=\"cabana-header-account\">\n {this.state.isGithubAuthenticated ? (\n <div>\n <p>GitHub Authenticated</p>\n <p\n className=\"cabana-header-account-signout\"\n onClick={this.githubSignOut}\n >\n Sign out\n </p>\n </div>\n ) : (\n this.loginWithGithub()\n )}\n </div>\n </div>\n <div className=\"cabana-window\">\n <Meta\n url={this.state.route ? route.url : null}\n messages={messages}\n selectedMessages={selectedMessages}\n updateSelectedMessages={this.updateSelectedMessages}\n showEditMessageModal={this.showEditMessageModal}\n currentParts={currentParts}\n onMessageSelected={this.onMessageSelected}\n onMessageUnselected={this.onMessageUnselected}\n showLoadDbc={this.showLoadDbc}\n showSaveDbc={this.showSaveDbc}\n dbcFilename={dbcFilename}\n dbcLastSaved={dbcLastSaved}\n dongleId={this.props.dongleId}\n name={this.props.name}\n route={route}\n seekTime={seekTime}\n seekIndex={seekIndex}\n shareUrl={shareUrl}\n maxByteStateChangeCount={maxByteStateChangeCount}\n isDemo={this.props.isDemo}\n live={live}\n saveLog={debounce(this.downloadLogAsCSV, 500)}\n />\n {route || live ? (\n <Explorer\n url={route ? route.url : null}\n live={live}\n messages={messages}\n thumbnails={thumbnails}\n selectedMessage={selectedMessage}\n onConfirmedSignalChange={this.onConfirmedSignalChange}\n onSeek={this.onSeek}\n onUserSeek={this.onUserSeek}\n canFrameOffset={canFrameOffset}\n firstCanTime={firstCanTime}\n seekTime={seekTime}\n startTime={startTime}\n startSegments={segments}\n seekIndex={seekIndex}\n currentParts={currentParts}\n selectedPart={currentPart}\n partsLoaded={partsLoaded}\n autoplay={this.props.autoplay}\n showEditMessageModal={this.showEditMessageModal}\n onPartChange={this.onPartChange}\n routeStartTime={\n route ? route.start_time : Moment()\n }\n videoOffset={ (this.state.firstFrameTime && this.state.routeInitTime) ? this.state.firstFrameTime - this.state.routeInitTime : 0 }\n partsCount={route ? route.proclog : 0}\n />\n ) : null}\n </div>\n\n {this.state.showOnboarding ? (\n <OnboardingModal\n handlePandaConnect={this.handlePandaConnect}\n attemptingPandaConnection={this.state.attemptingPandaConnection}\n routes={this.state.routes}\n />\n ) : null}\n\n {this.state.showLoadDbc ? (\n <LoadDbcModal\n onDbcSelected={this.onDbcSelected}\n handleClose={this.hideLoadDbc}\n openDbcClient={this.openDbcClient}\n loginWithGithub={this.loginWithGithub()}\n />\n ) : null}\n\n {this.state.showSaveDbc ? (\n <SaveDbcModal\n dbc={this.state.dbc}\n sourceDbcFilename={this.state.dbcFilename}\n onDbcSaved={this.onDbcSaved}\n handleClose={this.hideSaveDbc}\n openDbcClient={this.openDbcClient}\n hasGithubAuth={this.props.githubAuthToken !== null}\n loginWithGithub={this.loginWithGithub()}\n />\n ) : null}\n\n {this.state.showEditMessageModal ? (\n <EditMessageModal\n handleClose={this.hideEditMessageModal}\n handleSave={this.onMessageFrameEdited}\n message={this.state.messages[this.state.editMessageModalMessage]}\n />\n ) : null}\n </div>\n );\n }\n}\n\nCanExplorer.propTypes = {\n dongleId: PropTypes.string,\n name: PropTypes.string,\n dbc: PropTypes.instanceOf(DBC),\n dbcFilename: PropTypes.string,\n githubAuthToken: PropTypes.string,\n autoplay: PropTypes.bool,\n max: PropTypes.number,\n url: PropTypes.string,\n startTime: PropTypes.number,\n segments: PropTypes.array\n};\n","import { GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL } from '../config';\nimport { objToQuery } from '../utils/url';\n\nexport function authorizeUrl(route) {\n const params = {\n client_id: GITHUB_CLIENT_ID,\n redirect_uri: GITHUB_REDIRECT_URL,\n scope: 'user:email public_repo',\n state: JSON.stringify({ route })\n };\n\n return `http://github.com/login/oauth/authorize?${objToQuery(params)}`;\n}\n","import LogEntries from './LogEntries';\nimport { LOGENTRIES_TOKEN } from '../config';\n\nclass CloudLog {\n constructor() {\n LogEntries.init({\n token: LOGENTRIES_TOKEN,\n no_format: true,\n catchall: false\n });\n this.context = {};\n }\n\n bind(obj) {\n this.context.update(obj);\n }\n\n emit(message, level = 'log') {\n if (typeof global.__JEST__ !== 'undefined') {\n // Don't log in testing environment\n return;\n }\n\n const entry = {\n ctx: this.context,\n created: new Date().getTime() / 1000,\n msg: message,\n src: 'JSCloudLog'\n };\n\n if (level === 'log') {\n LogEntries.log(entry);\n } else if (level === 'warn') {\n LogEntries.warn(entry);\n } else if (level === 'error') {\n LogEntries.error(entry);\n }\n }\n\n log(message) {\n this.emit(message);\n }\n\n warn(message) {\n this.emit(message, 'warn');\n }\n\n error(message) {\n this.emit(message, 'error');\n }\n}\n\nexport default new CloudLog();\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { StyleSheet } from 'aphrodite/no-important';\nimport css from '../utils/css';\n\nimport SignalLegend from './SignalLegend';\nimport Signal from '../models/can/signal';\nimport { shade } from '../utils/color';\nimport DbcUtils from '../utils/dbc';\n\n/*\nAddSignals component draws an 8x8 matrix\nrepresenting the bytes in a CAN message, alongside\na signal legend. Dragging on the matrix\neither extends or creates a signal, which is\nconfigurable in the legend.\n*/\n\nconst Styles = StyleSheet.create({\n bit: {\n margin: 0,\n padding: 12,\n userSelect: 'none',\n cursor: 'pointer',\n textAlign: 'center',\n position: 'relative'\n },\n bitSelectedStyle: {\n backgroundColor: 'rgba(0,119,158,0.5)'\n },\n bitSignificance: {\n fontSize: 12,\n display: 'block',\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n margin: '0 auto'\n },\n highlightedSignalTitle: {\n backgroundColor: 'rgba(0,0,0,0.2)'\n }\n});\n\nexport default class AddSignals extends Component {\n static propTypes = {\n message: PropTypes.object,\n onConfirmedSignalChange: PropTypes.func,\n messageIndex: PropTypes.number,\n onSignalPlotChange: PropTypes.func,\n plottedSignalUids: PropTypes.array,\n selectedMessageKey: PropTypes.string\n };\n\n constructor(props) {\n super(props);\n\n let signals = {};\n if (props.message && props.message.frame && props.message.frame.signals) {\n signals = this.copySignals(props.message.frame.signals);\n }\n\n this.state = {\n bits: [],\n signals,\n signalStyles: this.calcSignalStyles(signals),\n highlightedSignal: null,\n dragStartBit: null,\n dragSignal: null,\n dragCurrentBit: null\n };\n }\n\n copySignals(signals) {\n return Object.entries(signals).reduce(\n (signalsCopy, [signalName, signal]) => {\n signalsCopy[signalName] = Object.assign(Object.create(signal), signal);\n return signalsCopy;\n },\n {}\n );\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n return (\n nextProps.message.hexData !== this.props.message.hexData\n || nextProps.messageIndex !== this.props.messageIndex\n || JSON.stringify(nextProps.plottedSignalUids)\n !== JSON.stringify(this.props.plottedSignalUids)\n || JSON.stringify(this.state) !== JSON.stringify(nextState)\n );\n }\n\n signalColorStyle(signal) {\n const colors = signal.getColors(this.props.selectedMessageKey);\n\n let colorRgbStr;\n let backgroundColor;\n if (this.state && this.state.highlightedSignal === signal.name) {\n // when signal highlighted,\n // darkened background and lightened text.\n\n const darkenedColors = shade(colors, -0.5);\n const lightenedColors = shade(colors, 0.9);\n colorRgbStr = `rgb(${lightenedColors.join(',')})`;\n backgroundColor = `rgba(${darkenedColors.join(',')},0.5)`;\n } else {\n const colorsCommaSep = colors.join(',');\n colorRgbStr = `rgb(${colorsCommaSep})`;\n backgroundColor = `rgba(${colorsCommaSep},0.2)`;\n }\n\n const style = StyleSheet.create({\n signal: { color: colorRgbStr, backgroundColor }\n }).signal;\n return style;\n }\n\n updateSignalStyles = () => {\n const signalStyles = this.calcSignalStyles(this.state.signals);\n\n this.setState({ signalStyles });\n };\n\n calcSignalStyles(signals) {\n const signalStyles = {};\n Object.values(signals).forEach((signal) => {\n signalStyles[signal.name] = this.signalColorStyle(signal);\n });\n\n return signalStyles;\n }\n\n componentWillReceiveProps(newProps) {\n if (newProps.message.address !== this.props.message.address\n || newProps.selectedMessageKey !== this.props.selectedMessageKey) {\n const signals = newProps.message.frame ? newProps.message.frame.signals : {};\n\n this.setState(\n { signals: this.copySignals(signals) },\n this.updateSignalStyles\n );\n }\n }\n\n signalForBit(bitIdx) {\n // bitIdx in [0,64)\n // returns instance of Signal\n\n return Object.values(this.state.signals).filter(\n (signal) => signal.bitDescription(bitIdx) !== null\n )[0];\n }\n\n onSignalHover = (signal) => {\n if (!signal) return;\n\n this.setState({ highlightedSignal: signal.name }, this.updateSignalStyles);\n };\n\n signalBitIndex(bitIdx, signal) {\n // todo does this work for both big and little endian?\n let { startBit } = signal;\n if (!signal.isLittleEndian) {\n startBit = DbcUtils.bigEndianBitIndex(startBit);\n }\n return bitIdx - startBit;\n }\n\n onBitHover = (bitIdx, signal) => {\n let { dragStartBit, signals, dragSignal } = this.state;\n\n if (dragStartBit !== null) {\n if (dragSignal !== null) {\n signals = this.copySignals(signals);\n dragSignal = Object.assign(Object.create(dragSignal), dragSignal);\n\n if (dragStartBit === dragSignal.startBit && dragSignal.size > 1) {\n if (!dragSignal.isLittleEndian) {\n // should not be able to drag the msb past the lsb\n const hoveredBigEndian = DbcUtils.bigEndianBitIndex(bitIdx);\n const lsbBigEndian = dragSignal.lsbBitNumber();\n\n if (hoveredBigEndian > lsbBigEndian) {\n return;\n }\n } else {\n // should not be able to drag the lsb past the msb\n if (bitIdx > dragSignal.msbBitIndex()) {\n return;\n }\n }\n\n const diff = bitIdx - dragStartBit;\n\n if (dragSignal.isLittleEndian) {\n dragSignal.size -= diff;\n } else if (dragSignal.bitDescription(bitIdx) === null) {\n dragSignal.size += Math.abs(diff);\n } else {\n dragSignal.size -= Math.abs(diff);\n }\n\n dragSignal.startBit += diff;\n\n signals[dragSignal.name] = dragSignal;\n dragStartBit = dragSignal.startBit;\n } else if (dragSignal.size === 1) {\n // 1-bit signals can be dragged in either direction\n if (Math.floor(bitIdx / 8) === Math.floor(dragStartBit / 8)) {\n if (bitIdx > dragStartBit) {\n if (dragSignal.isLittleEndian) {\n dragSignal.size = bitIdx - dragSignal.startBit;\n } else {\n dragSignal.startBit = bitIdx;\n dragSignal.size = bitIdx - dragStartBit + 1;\n dragStartBit = bitIdx;\n }\n } else if (dragSignal.isLittleEndian) {\n dragSignal.startBit = bitIdx;\n dragSignal.size = dragStartBit - bitIdx + 1;\n dragStartBit = bitIdx;\n } else {\n dragSignal.size = dragStartBit - bitIdx + 1;\n dragStartBit = bitIdx;\n }\n }\n\n signals[dragSignal.name] = dragSignal;\n } else if (\n dragSignal.isLittleEndian\n && dragStartBit === dragSignal.msbBitIndex()\n ) {\n if (bitIdx < dragSignal.startBit) {\n // should not be able to drag the MSB past the LSB\n return;\n }\n const diff = bitIdx - dragStartBit;\n if (dragSignal.bitDescription(bitIdx) === null) {\n dragSignal.size += Math.abs(diff);\n } else {\n dragSignal.size -= Math.abs(diff);\n }\n signals[dragSignal.name] = dragSignal;\n dragStartBit = dragSignal.msbBitIndex();\n } else if (\n !dragSignal.isLittleEndian\n && dragStartBit === dragSignal.lsbBitIndex()\n ) {\n const diff = bitIdx - dragStartBit;\n if (dragSignal.bitDescription(bitIdx) === null) {\n dragSignal.size += Math.abs(diff);\n } else {\n dragSignal.size -= Math.abs(diff);\n }\n signals[dragSignal.name] = dragSignal;\n dragStartBit = dragSignal.lsbBitIndex();\n }\n this.setState({\n signals,\n dragSignal,\n dragCurrentBit: bitIdx,\n dragStartBit\n });\n } else {\n this.setState({ dragCurrentBit: bitIdx });\n }\n }\n if (signal) {\n this.onSignalHover(signal);\n }\n };\n\n onSignalHoverEnd = (signal) => {\n if (!signal) return;\n\n this.setState({ highlightedSignal: null }, this.updateSignalStyles);\n };\n\n nextNewSignalName() {\n const existingNames = Object.keys(this.state.signals);\n let signalNum = 1;\n let signalName;\n do {\n signalName = `NEW_SIGNAL_${signalNum}`;\n signalNum++;\n } while (existingNames.indexOf(signalName) !== -1);\n\n return signalName;\n }\n\n onBitMouseDown(dragStartBit, dragSignal) {\n this.setState({\n dragStartBit,\n dragSignal: dragSignal || null\n });\n }\n\n createSignal({ startBit, size, isLittleEndian }) {\n const signal = new Signal({\n name: this.nextNewSignalName(),\n startBit,\n size,\n isLittleEndian\n });\n let { signals } = this.state;\n signals = { ...signals };\n signals[signal.name] = signal;\n\n this.setState({ signals }, this.propagateUpSignalChange);\n }\n\n createSignalIfNotExtendingOne(dragStartBit, dragEndBit) {\n if (this.state.dragSignal === null) {\n // check for overlapping bits\n for (let i = dragStartBit; i <= dragEndBit; i++) {\n if (this.signalForBit(i) !== undefined) {\n // Don't create signal if a signal is already defined in the selected range.\n return;\n }\n }\n const isDragAcrossSingleByte = Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8);\n const isDragDirectionUp = !isDragAcrossSingleByte && dragEndBit < dragStartBit;\n\n let isLittleEndian;\n if (isDragAcrossSingleByte || !isDragDirectionUp) {\n isLittleEndian = dragStartBit % 8 < 4;\n } else {\n isLittleEndian = dragStartBit % 8 >= 4;\n }\n let size;\n let startBit = dragStartBit;\n\n if (isDragAcrossSingleByte) {\n size = Math.abs(dragEndBit - dragStartBit) + 1;\n } else if (isLittleEndian) {\n if (dragEndBit > dragStartBit) {\n startBit = dragStartBit;\n size = dragEndBit - dragStartBit + 1;\n } else {\n startBit = dragEndBit;\n size = dragStartBit - dragEndBit + 1;\n }\n } else {\n if (dragEndBit < dragStartBit) {\n startBit = dragEndBit;\n }\n size = Math.abs(\n DbcUtils.bigEndianBitIndex(dragEndBit)\n - DbcUtils.bigEndianBitIndex(dragStartBit)\n ) + 1;\n }\n\n this.createSignal({ startBit, size, isLittleEndian });\n }\n }\n\n onBitMouseUp(dragEndBit, signal) {\n if (this.state.dragStartBit !== null) {\n const { dragStartBit } = this.state;\n\n if (dragEndBit !== dragStartBit) {\n // one-bit signal requires double click\n // see onBitDoubleClick\n this.createSignalIfNotExtendingOne(dragStartBit, dragEndBit);\n }\n this.propagateUpSignalChange();\n this.resetDragState();\n }\n }\n\n byteValueHex(byteIdx) {\n const { entries } = this.props.message;\n if (this.props.messageIndex < entries.length) {\n const entry = entries[this.props.messageIndex];\n\n return entry.hexData.substr(byteIdx * 2, 2);\n }\n return '--';\n }\n\n bitValue(byteIdx, byteBitIdx) {\n const { entries } = this.props.message;\n if (this.props.messageIndex < entries.length) {\n const entry = entries[this.props.messageIndex];\n const data = Buffer.from(entry.hexData, 'hex');\n if (byteIdx >= data.length) {\n return '-';\n }\n const byte = data.readInt8(byteIdx);\n return (byte >> byteBitIdx) & 1;\n }\n return '-';\n }\n\n bitIsContainedInSelection(bitIdx, isLittleEndian = false) {\n const { dragStartBit, dragCurrentBit } = this.state;\n\n if (isLittleEndian || dragStartBit % 8 < 4) {\n return (\n dragStartBit !== null\n && dragCurrentBit !== null\n && bitIdx >= dragStartBit\n && bitIdx <= dragCurrentBit\n );\n }\n const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit);\n const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit);\n const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx);\n return (\n dragStartBit !== null\n && dragCurrentBit !== null\n && bigEndianBitIdx >= bigEndianStartBit\n && bigEndianBitIdx <= bigEndianCurrentBit\n );\n }\n\n onBitDoubleClick(startBit, signal) {\n if (signal === undefined) {\n this.createSignal({ startBit, size: 1, isLittleEndian: false });\n }\n }\n\n renderBitMatrix() {\n const { message } = this.props;\n const rows = [];\n let rowCount;\n if (message.frame && message.frame.size) {\n rowCount = Math.floor((message.frame.size * 8) / 8);\n } else {\n rowCount = 8;\n }\n\n for (let i = 0; i < rowCount; i++) {\n const rowBits = [];\n for (let j = 7; j >= 0; j--) {\n const bitIdx = i * 8 + j;\n const signal = this.signalForBit(bitIdx);\n let bitStyle = null;\n let bitSignificance = '';\n if (signal) {\n bitStyle = this.state.signalStyles[signal.name] || null;\n const bitDesc = signal.bitDescription(bitIdx);\n bitSignificance = bitDesc.isMsb ? 'msb' : bitDesc.isLsb ? 'lsb' : '';\n } else if (this.bitIsContainedInSelection(bitIdx)) {\n bitStyle = Styles.bitSelectedStyle;\n }\n const className = css('bit', Styles.bit, bitStyle);\n const bitValue = this.bitValue(i, j);\n\n rowBits.push(\n <td\n key={j.toString()}\n className={className}\n onMouseEnter={() => this.onBitHover(bitIdx, signal)}\n onMouseLeave={() => this.onSignalHoverEnd(signal)}\n onMouseDown={this.onBitMouseDown.bind(this, bitIdx, signal)}\n onMouseUp={this.onBitMouseUp.bind(this, bitIdx, signal)}\n onDoubleClick={() => this.onBitDoubleClick(bitIdx, signal)}\n >\n <span>{bitValue}</span>\n <span className={css(Styles.bitSignificance)}>\n {bitSignificance}\n </span>\n </td>\n );\n }\n\n rowBits.push(<td key=\"hex-repr\">{this.byteValueHex(i)}</td>);\n rows.push(<tr key={i.toString()}>{rowBits}</tr>);\n }\n\n return (\n <div className=\"cabana-explorer-signals-matrix\">\n <table cellSpacing={0} onMouseLeave={this.resetDragState}>\n <tbody>{rows}</tbody>\n </table>\n </div>\n );\n }\n\n resetDragState = () => {\n this.setState({\n dragStartBit: null,\n dragSignal: null,\n dragCurrentBit: null\n });\n };\n\n onTentativeSignalChange = (signal) => {\n // Tentative signal changes are not propagated up\n // but their effects are displayed in the bitmatrix\n const { signals } = this.state;\n signals[signal.name] = signal;\n this.setState({ signals });\n };\n\n onSignalChange = (signal, oldSignal) => {\n const { signals } = this.state;\n\n for (const signalName in signals) {\n if (signals[signalName].uid === signal.uid) {\n delete signals[signalName];\n }\n }\n signals[signal.name] = signal;\n\n this.setState({ signals }, this.propagateUpSignalChange);\n };\n\n onSignalRemove = (signal) => {\n const { signals } = this.state;\n delete signals[signal.name];\n this.setState({ signals }, this.propagateUpSignalChange);\n };\n\n propagateUpSignalChange() {\n const { signals } = this.state;\n\n this.props.onConfirmedSignalChange(\n this.props.message,\n this.copySignals(signals)\n );\n }\n\n onSignalPlotChange = (shouldPlot, signalUid) => {\n const { message } = this.props;\n\n this.props.onSignalPlotChange(shouldPlot, message.id, signalUid);\n };\n\n render() {\n const { selectedMessageKey } = this.props;\n return (\n <div className=\"cabana-explorer-signals-controller\">\n {Object.keys(this.state.signals).length === 0 ? (\n <p>Double click or drag to add a signal</p>\n ) : null}\n {this.props.message.entries[this.props.messageIndex] ? (\n <div className=\"cabana-explorer-signals-time\">\n <p>\n time:\n {' '}\n {this.props.message.entries[\n this.props.messageIndex\n ].relTime.toFixed(3)}\n </p>\n </div>\n ) : null}\n {this.props.message.isLogEvent || this.renderBitMatrix()}\n <SignalLegend\n isLogEvent={!!this.props.message.isLogEvent}\n signals={this.state.signals}\n signalStyles={this.state.signalStyles}\n highlightedSignal={this.state.highlightedSignal}\n onSignalHover={this.onSignalHover}\n onSignalHoverEnd={this.onSignalHoverEnd}\n onTentativeSignalChange={this.onTentativeSignalChange}\n onSignalChange={this.onSignalChange}\n onSignalRemove={this.onSignalRemove}\n onSignalPlotChange={this.onSignalPlotChange}\n plottedSignalUids={this.props.plottedSignalUids}\n selectedMessageKey={selectedMessageKey}\n />\n </div>\n );\n }\n}\n","import rightPad from 'right-pad';\nimport CloudLog from '../../logging/CloudLog';\nimport Signal from './signal';\nimport Frame from './frame';\nimport BoardUnit from './BoardUnit';\nimport DbcUtils from '../../utils/dbc';\nimport * as LogSignals from './logSignals';\n\nconst { UINT64 } = require('cuint');\n\nconst DBC_COMMENT_RE = /^CM_ *\"(.*)\";/;\nconst DBC_COMMENT_MULTI_LINE_RE = /^CM_ *\"(.*)/;\n\nconst MSG_RE = /^BO_ (\\w+) (\\w+) *: (\\w+) (\\w+)/;\n\nconst SIGNAL_RE = /^SG_ (\\w+) : (\\d+)\\|(\\d+)@(\\d+)([+|-]) \\(([0-9.+-eE]+),([0-9.+-eE]+)\\) \\[([0-9.+-eE]+)\\|([0-9.+-eE]+)\\] \"(.*)\" (.*)/;\n// Multiplexed signal\nconst MP_SIGNAL_RE = /^SG_ (\\w+) (\\w+) *: (\\d+)\\|(\\d+)@(\\d+)([+|-]) \\(([0-9.+-eE]+),([0-9.+-eE]+)\\) \\[([0-9.+-eE]+)\\|([0-9.+-eE]+)\\] \"(.*)\" (.*)/;\n\nconst VAL_RE = /^VAL_ (\\w+) (\\w+) (.*);/;\nconst VAL_TABLE_RE = /^VAL_TABLE_ (\\w+) (.*);/;\n\nconst MSG_TRANSMITTER_RE = /^BO_TX_BU_ ([0-9]+) *: *(.+);/;\n\nconst SIGNAL_COMMENT_RE = /^CM_ SG_ *(\\w+) *(\\w+) *\"(.*)\";/;\nconst SIGNAL_COMMENT_MULTI_LINE_RE = /^CM_ SG_ *(\\w+) *(\\w+) *\"(.*)/;\n\n// Message Comments (CM_ BO_ )\nconst MESSAGE_COMMENT_RE = /^CM_ BO_ *(\\w+) *\"(.*)\";/;\nconst MESSAGE_COMMENT_MULTI_LINE_RE = /^CM_ BO_ *(\\w+) *\"(.*)/;\n\nconst BOARD_UNIT_RE = /^BU_:(.*)/;\nconst BOARD_UNIT_COMMENT_RE = /^CM_ BU_ *(\\w+) *\"(.*)\";/;\nconst BOARD_UNIT_COMMENT_MULTI_LINE_RE = /^CM_ BU_ *(\\w+) *\"(.*)/;\n\n// Follow ups are used to parse multi-line comment definitions\nconst FOLLOW_UP_DBC_COMMENT = 'FollowUpDbcComment';\nconst FOLLOW_UP_SIGNAL_COMMENT = 'FollowUpSignalComment';\nconst FOLLOW_UP_MSG_COMMENT = 'FollowUpMsgComment';\nconst FOLLOW_UP_BOARD_UNIT_COMMENT = 'FollowUpBoardUnitComment';\n\nfunction floatOrInt(numericStr) {\n if (Number.isInteger(numericStr)) {\n return parseInt(numericStr, 10);\n }\n return parseFloat(numericStr);\n}\n\nexport function swapOrder(arr, wordSize, gSize) {\n const swappedWords = [];\n\n for (let i = 0; i < arr.length; i += wordSize) {\n const word = arr.slice(i, i + wordSize);\n for (let j = wordSize - gSize; j > -gSize; j -= gSize) {\n swappedWords.push(word.slice(j, j + gSize));\n }\n }\n\n return swappedWords.join('');\n}\n\nexport default class DBC {\n constructor(dbcString) {\n this.boardUnits = [];\n this.comments = [];\n this.messages = new Map();\n\n if (dbcString !== undefined) {\n this.dbcText = dbcString;\n this.importDbcString(dbcString);\n }\n }\n\n getMessageFrame(address) {\n if (LogSignals.isLogAddress(address)) {\n return LogSignals.frameForAddress(address);\n }\n return this.messages.get(address);\n }\n\n nextNewFrameName() {\n const messageNames = [];\n\n for (const msg of this.messages.values()) {\n messageNames.push(msg.name);\n }\n\n let msgNum = 1;\n let msgName;\n do {\n msgName = `NEW_MSG_${msgNum}`;\n msgNum++;\n } while (messageNames.indexOf(msgName) !== -1);\n\n return msgName;\n }\n\n updateBoardUnits() {\n const boardUnitNames = this.boardUnits.map((bu) => bu.name);\n const missingBoardUnits = Array.from(this.messages.entries())\n .map(([msgId, frame]) => Object.values(frame.signals))\n .reduce((arr, signals) => arr.concat(signals), [])\n .map((signal) => signal.receiver)\n .reduce((arr, receivers) => arr.concat(receivers), [])\n .filter((recv, idx, array) => array.indexOf(recv) === idx)\n .filter((recv) => boardUnitNames.indexOf(recv) === -1)\n .map((recv) => new BoardUnit(recv));\n\n this.boardUnits = this.boardUnits.concat(missingBoardUnits);\n }\n\n text() {\n this.updateBoardUnits();\n\n let txt = 'VERSION \"\"\\n\\n\\n';\n txt += `NS_ :${this._newSymbols()}`;\n txt += '\\n\\nBS_:\\n';\n\n const boardUnitsText = this.boardUnits.map((bu) => bu.text()).join(' ');\n txt += `\\nBU_: ${boardUnitsText}\\n\\n\\n`;\n\n const frames = [];\n for (const frame of this.messages.values()) {\n frames.push(frame);\n }\n txt += `${frames.map((f) => f.text()).join('\\n\\n')}\\n\\n`;\n\n const messageTxs = frames\n .map((f) => [f.id, f.transmitters.slice(1)])\n .filter(([addr, txs]) => txs.length > 0);\n txt += `${messageTxs\n .map(([addr, txs]) => `BO_TX_BU_ ${addr} : ${txs.join(',')};`)\n .join('\\n')}\\n\\n\\n`;\n\n txt += this.boardUnits\n .filter((bu) => bu.comment !== null)\n .map((bu) => `CM_ BU_ ${bu.name} \"${bu.comment}\";`)\n .join('\\n');\n\n txt += frames\n .filter((f) => f.comment !== null)\n .map((msg) => `CM_ BO_ ${msg.address} \"${msg.comment}\";`)\n .join('\\n');\n\n const signalsByMsgId = frames\n .map((f) => Object.values(f.signals).map((sig) => [f.id, sig]))\n .reduce((s1, s2) => s1.concat(s2), []);\n\n txt += `${signalsByMsgId\n .filter(([msgAddr, sig]) => sig.comment !== null)\n .map(\n ([msgAddr, sig]) => `CM_ SG_ ${msgAddr} ${sig.name} \"${sig.comment}\";`\n )\n .join('\\n')}\\n`;\n\n txt += `${signalsByMsgId\n .filter(([msgAddr, sig]) => sig.valueDescriptions.size > 0)\n .map(([msgAddr, sig]) => sig.valueDescriptionText(msgAddr))\n .join('\\n')}\\n`;\n\n txt += this.comments.map((comment) => `CM_ \"${comment}\";`).join('\\n');\n\n return `${txt.trim()}\\n`;\n }\n\n getMessageName(msgId) {\n const msg = this.getMessageFrame(msgId);\n if (msg && msg.frame) return msg.frame.name;\n return null;\n }\n\n getSignals(msgId) {\n const msg = this.getMessageFrame(msgId);\n if (msg) return msg.signals;\n return {};\n }\n\n createFrame(msgId) {\n const msg = new Frame({\n name: this.nextNewFrameName(),\n id: msgId,\n size: 8\n });\n\n this.messages.set(msgId, msg);\n return msg;\n }\n\n setSignals(msgId, signals) {\n const msg = this.getMessageFrame(msgId);\n if (msg) {\n const newMsg = Object.assign(Object.create(msg), msg);\n newMsg.signals = signals;\n this.messages.set(msgId, newMsg);\n } else {\n const msg = this.createFrame(msgId);\n msg.signals = signals;\n\n this.messages.set(msgId, msg);\n this.updateBoardUnits();\n }\n }\n\n addSignal(msgId, signal) {\n const msg = this.getMessageFrame(msgId);\n\n if (msg) {\n msg.signals[signal.name] = signal;\n this.updateBoardUnits();\n }\n }\n\n importDbcString(dbcString) {\n const warnings = [];\n const messages = new Map();\n let boardUnits = [];\n const valueTables = new Map();\n let id = 0;\n let followUp = null;\n\n const lines = dbcString.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n let line = lines[i].trim();\n\n if (line.length === 0) continue;\n\n if (followUp != null) {\n const { type, data } = followUp;\n line = line.replace(/\" *;/, '');\n let followUpLine = `\\n${line.substr(0, line.length)}`;\n if (line.indexOf('\"') !== -1) {\n followUp = null;\n followUpLine = followUpLine.substr(0, followUpLine.length - 1);\n }\n if (type === FOLLOW_UP_SIGNAL_COMMENT) {\n const signal = data;\n signal.comment += followUpLine;\n } else if (type === FOLLOW_UP_MSG_COMMENT) {\n const msg = data;\n msg.comment += followUpLine;\n } else if (type === FOLLOW_UP_BOARD_UNIT_COMMENT) {\n const boardUnit = data;\n boardUnit.comment += followUpLine;\n } else if (type === FOLLOW_UP_DBC_COMMENT) {\n // const comment = data;\n const partialComment = this.comments[this.comments.length - 1];\n this.comments[this.comments.length - 1] = partialComment + followUpLine;\n }\n }\n\n if (line.indexOf('BO_ ') === 0) {\n const matches = line.match(MSG_RE);\n if (matches === null) {\n warnings.push(\n `failed to parse message definition on line ${i + 1} -- ${line}`\n );\n continue;\n }\n let [idString, name, size, transmitter] = matches.slice(1);\n id = parseInt(idString, 0); // 0 radix parses hex or dec\n size = parseInt(size, 10);\n const frame = new Frame({\n name,\n id,\n size,\n transmitters: [transmitter]\n });\n messages.set(id, frame);\n } else if (line.indexOf('SG_') === 0) {\n let matches = line.match(SIGNAL_RE);\n\n if (matches === null) {\n matches = line.match(MP_SIGNAL_RE);\n if (matches === null) {\n warnings.push(\n `failed to parse signal definition on line ${i + 1} -- ${line}`\n );\n continue;\n }\n // for now, ignore multiplex which is matches[1]\n matches = matches[1] + matches.slice(3);\n } else {\n matches = matches.slice(1);\n }\n\n let [\n name,\n startBit,\n size,\n isLittleEndian,\n isSigned,\n factor,\n offset,\n min,\n max,\n unit,\n receiverStr\n ] = matches;\n startBit = parseInt(startBit, 10);\n size = parseInt(size, 10);\n isLittleEndian = parseInt(isLittleEndian, 10) === 1;\n isSigned = isSigned === '-';\n factor = floatOrInt(factor);\n offset = floatOrInt(offset);\n min = floatOrInt(min);\n max = floatOrInt(max);\n const receiver = receiverStr.split(',').map((s) => s.trim());\n\n const signalProperties = {\n name,\n startBit,\n size,\n isLittleEndian,\n isSigned,\n factor,\n offset,\n unit,\n min,\n max,\n receiver\n };\n const signal = new Signal(signalProperties);\n\n if (messages.get(id) !== undefined) {\n messages.get(id).signals[name] = signal;\n } else {\n CloudLog.warn(\n `importDbcString: could not add signal: ${name} due to missing message: ${id}`\n );\n }\n } else if (line.indexOf('VAL_ ') === 0) {\n const matches = line.match(VAL_RE);\n\n if (matches !== null) {\n let [messageId, signalName, vals] = matches.slice(1);\n vals = vals\n .split('\"')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n\n messageId = parseInt(messageId, 10);\n const msg = messages.get(messageId);\n const signal = msg.signals[signalName];\n if (signal === undefined) {\n warnings.push(\n `could not find signal for value description on line ${i\n + 1} -- ${line}`\n );\n continue;\n }\n for (let i = 0; i < vals.length; i += 2) {\n const value = vals[i].trim();\n const description = vals[i + 1].trim();\n signal.valueDescriptions.set(value, description);\n }\n } else {\n warnings.push(\n `failed to parse value description on line ${i + 1} -- ${line}`\n );\n }\n } else if (line.indexOf('VAL_TABLE_ ') === 0) {\n const matches = line.match(VAL_TABLE_RE);\n\n if (matches !== null) {\n const table = new Map();\n let [tableName, items] = matches.slice(1);\n items = items\n .split('\"')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n\n for (let i = 0; i < items.length; i += 2) {\n const key = items[i];\n const value = items[i + 1];\n table.set(key, value);\n }\n valueTables.set(tableName, table);\n } else {\n warnings.push(\n `failed to parse value table on line ${i + 1} -- ${line}`\n );\n }\n } else if (line.indexOf('BO_TX_BU_ ') === 0) {\n const matches = line.match(MSG_TRANSMITTER_RE);\n\n if (matches !== null) {\n let [messageId, transmitter] = matches.slice(1);\n messageId = parseInt(messageId, 10);\n\n const msg = messages.get(messageId);\n msg.transmitters.push(transmitter);\n messages.set(messageId, msg);\n } else {\n warnings.push(\n `failed to parse message transmitter definition on line ${i\n + 1} -- ${line}`\n );\n }\n } else if (line.indexOf('CM_ SG_ ') === 0) {\n let matches = line.match(SIGNAL_COMMENT_RE);\n let hasFollowUp = false;\n if (matches === null) {\n matches = line.match(SIGNAL_COMMENT_MULTI_LINE_RE);\n hasFollowUp = true;\n }\n if (matches === null) {\n warnings.push(\n `failed to parse signal comment on line ${i + 1} -- ${line}`\n );\n continue;\n }\n\n let [messageId, signalName, comment] = matches.slice(1);\n\n messageId = parseInt(messageId, 10);\n const msg = messages.get(messageId);\n if (msg === undefined) {\n warnings.push(`failed to parse signal comment on line ${i\n + 1} -- ${line}:\n message id ${messageId} does not exist prior to this line`);\n continue;\n }\n const signal = msg.signals[signalName];\n if (signal === undefined) {\n warnings.push(\n `failed to parse signal comment on line ${i + 1} -- ${line}`\n );\n continue;\n } else {\n signal.comment = comment;\n messages.set(messageId, msg);\n }\n\n if (hasFollowUp) {\n followUp = { type: FOLLOW_UP_SIGNAL_COMMENT, data: signal };\n }\n } else if (line.indexOf('CM_ BO_ ') === 0) {\n let matches = line.match(MESSAGE_COMMENT_RE);\n let hasFollowUp = false;\n if (matches === null) {\n matches = line.match(MESSAGE_COMMENT_MULTI_LINE_RE);\n hasFollowUp = true;\n if (matches === null) {\n warnings.push(\n `failed to message comment on line ${i + 1} -- ${line}`\n );\n continue;\n }\n }\n\n let [messageId, comment] = matches.slice(1);\n messageId = parseInt(messageId, 10);\n const msg = messages.get(messageId);\n msg.comment = comment;\n\n if (hasFollowUp) {\n followUp = { type: FOLLOW_UP_MSG_COMMENT, data: msg };\n }\n } else if (line.indexOf('BU_: ') === 0) {\n const matches = line.match(BOARD_UNIT_RE);\n\n if (matches !== null) {\n const [boardUnitNameStr] = matches.slice(1);\n const newBoardUnits = boardUnitNameStr\n .split(' ')\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n .map((name) => new BoardUnit(name));\n\n boardUnits = boardUnits.concat(newBoardUnits);\n } else {\n warnings.push(\n `failed to parse board unit definition on line ${i + 1} -- ${line}`\n );\n continue;\n }\n } else if (line.indexOf('CM_ BU_ ') === 0) {\n let matches = line.match(BOARD_UNIT_COMMENT_RE);\n let hasFollowUp = false;\n if (matches === null) {\n matches = line.match(BOARD_UNIT_COMMENT_MULTI_LINE_RE);\n hasFollowUp = true;\n if (matches === null) {\n warnings.push(\n `failed to parse board unit comment on line ${i + 1} -- ${line}`\n );\n continue;\n }\n }\n\n const [boardUnitName, comment] = matches.slice(1);\n const boardUnit = boardUnits.find((bu) => bu.name === boardUnitName);\n if (boardUnit) {\n boardUnit.comment = comment;\n }\n\n if (hasFollowUp) {\n followUp = { type: FOLLOW_UP_BOARD_UNIT_COMMENT, data: boardUnit };\n }\n } else if (line.indexOf('CM_ ') === 0) {\n let matches = line.match(DBC_COMMENT_RE);\n let hasFollowUp = false;\n if (matches === null) {\n matches = line.match(DBC_COMMENT_MULTI_LINE_RE);\n if (matches === null) {\n warnings.push(\n `failed to parse dbc comment on line ${i + 1} -- ${line}`\n );\n continue;\n } else {\n hasFollowUp = true;\n }\n }\n\n const [comment] = matches.slice(1);\n this.comments.push(comment);\n if (hasFollowUp) {\n followUp = { type: FOLLOW_UP_DBC_COMMENT, data: comment };\n }\n }\n }\n\n // Disabled b/c live mode frequently calls this function\n // and executes way too many network requests\n if (warnings.length > 0) {\n // warnings.forEach((warning) => CloudLog.warn('importDbcString: ' + warning));\n // warnings.forEach((warning) => console.log('importDbcString: ' + warning));\n }\n\n this.messages = messages;\n this.boardUnits = boardUnits;\n this.valueTables = valueTables;\n }\n\n valueForInt64Signal(signalSpec, hexData) {\n const blen = hexData.length * 4;\n let value;\n let startBit;\n let dataBitPos;\n\n if (signalSpec.isLittleEndian) {\n value = UINT64(swapOrder(hexData, 16, 2), 16);\n startBit = signalSpec.startBit;\n dataBitPos = UINT64(startBit);\n } else {\n // big endian\n value = UINT64(hexData, 16);\n\n startBit = DbcUtils.bigEndianBitIndex(signalSpec.startBit);\n dataBitPos = UINT64(blen - (startBit + signalSpec.size));\n }\n if (dataBitPos < 0) {\n return null;\n }\n\n const rightHandAnd = UINT64(Math.pow(2, signalSpec.size) - 1);\n let ival = value\n .shiftr(dataBitPos)\n .and(rightHandAnd)\n .toNumber();\n\n if (signalSpec.isSigned && ival & Math.pow(2, signalSpec.size - 1)) {\n ival -= Math.pow(2, signalSpec.size);\n }\n ival = ival * signalSpec.factor + signalSpec.offset;\n return ival;\n }\n\n valueForInt32Signal(signalSpec, buf) {\n let startBit;\n if (signalSpec.isLittleEndian) {\n startBit = 64 - signalSpec.startBit - signalSpec.size;\n } else {\n let bitPos = (-signalSpec.startBit - 1) % 8;\n if (bitPos < 0) {\n bitPos += 8; // mimic python modulo behavior\n }\n\n startBit = Math.floor(signalSpec.startBit / 8) * 8 + bitPos;\n }\n\n let shiftAmount;\n let signalValue;\n const byteOffset = Math.min(4, Math.floor(signalSpec.startBit / 8));\n if (signalSpec.isLittleEndian) {\n signalValue = buf.readUInt32LE(byteOffset);\n shiftAmount = signalSpec.startBit - 8 * byteOffset;\n } else {\n signalValue = buf.readUInt32BE(byteOffset);\n shiftAmount = 32 - (startBit - 8 * byteOffset + signalSpec.size);\n }\n\n signalValue = (signalValue >>> shiftAmount) & ((1 << signalSpec.size) - 1);\n if (signalSpec.isSigned && signalValue >>> (signalSpec.size - 1)) {\n signalValue -= 1 << signalSpec.size;\n }\n\n return signalValue * signalSpec.factor + signalSpec.offset;\n }\n\n getSignalValues(messageId, data) {\n if (!this.messages.has(messageId) && !LogSignals.isLogAddress(messageId)) {\n return {};\n }\n const frame = this.getMessageFrame(messageId);\n\n const buffer = Buffer.from(data);\n let paddedBuffer = buffer;\n if (buffer.length !== 8) {\n // pad data it's 64 bits long\n const paddedDataHex = rightPad(buffer.toString('hex'), 16, '0');\n paddedBuffer = Buffer.from(paddedDataHex, 'hex');\n }\n const hexData = paddedBuffer.toString('hex');\n\n const signalValuesByName = {};\n Object.values(frame.signals).forEach((signalSpec) => {\n let value;\n if (signalSpec.size > 32) {\n value = this.valueForInt64Signal(signalSpec, hexData);\n } else {\n value = this.valueForInt32Signal(signalSpec, paddedBuffer);\n }\n signalValuesByName[signalSpec.name] = value;\n });\n\n return signalValuesByName;\n }\n\n getChffrMetricMappings() {\n const metricComment = this.comments.find(\n (comment) => comment.indexOf('CHFFR_METRIC') === 0\n );\n if (!metricComment) {\n return null;\n }\n\n return metricComment\n .split(';')\n .map((metric) => metric.trim().split(' '))\n .reduce(\n (metrics, [_, messageId, signalName, metricName, factor, offset]) => {\n metrics[metricName] = {\n messageId: parseInt(messageId, 10),\n signalName,\n factor: parseFloat(factor),\n offset: parseFloat(offset)\n };\n return metrics;\n },\n {}\n );\n }\n\n _newSymbols() {\n return `\n NS_DESC_\n CM_\n BA_DEF_\n BA_\n VAL_\n CAT_DEF_\n CAT_\n FILTER\n BA_DEF_DEF_\n EV_DATA_\n ENVVAR_DATA_\n SGTYPE_\n SGTYPE_VAL_\n BA_DEF_SGTYPE_\n BA_SGTYPE_\n SIG_TYPE_REF_\n VAL_TABLE_\n SIG_GROUP_\n SIG_VALTYPE_\n SIGTYPE_VALTYPE_\n BO_TX_BU_\n BA_DEF_REL_\n BA_REL_\n BA_DEF_DEF_REL_\n BU_SG_REL_\n BU_EV_REL_\n BU_BO_REL_\n SG_MUL_VAL_`;\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport Moment from 'moment';\nimport _ from 'lodash';\nimport cx from 'classnames';\nimport CommaAuth from '@commaai/my-comma-auth';\n\nimport { EXPLORER_URL } from '../../config';\nimport Modal from './baseModal';\n\nexport default class OnboardingModal extends Component {\n static propTypes = {\n handlePandaConnect: PropTypes.func,\n routes: PropTypes.array\n };\n\n static instructionalImages = {\n step2: require('../../images/webusb-enable-experimental-features.png'),\n step3: require('../../images/webusb-enable-webusb.png')\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n webUsbEnabled: !!navigator.usb,\n viewingUsbInstructions: false,\n pandaConnected: false\n };\n\n this.attemptPandaConnection = this.attemptPandaConnection.bind(this);\n this.toggleUsbInstructions = this.toggleUsbInstructions.bind(this);\n this.navigateToExplorer = this.navigateToExplorer.bind(this);\n }\n\n attemptPandaConnection() {\n if (!this.state.webUsbEnabled) {\n return;\n }\n this.props.handlePandaConnect();\n }\n\n toggleUsbInstructions() {\n this.setState({\n viewingUsbInstructions: !this.state.viewingUsbInstructions\n });\n }\n\n navigateToExplorer() {\n window.location.href = EXPLORER_URL;\n }\n\n filterRoutesWithCan(drive) {\n return drive.can === true;\n }\n\n renderPandaEligibility() {\n const { webUsbEnabled, pandaConnected } = this.state;\n const { attemptingPandaConnection } = this.props;\n if (!webUsbEnabled) {\n return (\n <p>\n <i className=\"fa fa-exclamation-triangle\" />\n <a onClick={this.toggleUsbInstructions}>\n <span>WebUSB is not enabled in your Chrome settings</span>\n </a>\n </p>\n );\n }\n if (!pandaConnected && attemptingPandaConnection) {\n return (\n <p>\n <i className=\"fa fa-spinner animate-spin\" />\n <span className=\"animate-pulse-opacity\">\n Waiting for panda USB connection\n </span>\n </p>\n );\n }\n }\n\n renderLogin() {\n return (\n <button\n onClick={this.navigateToExplorer}\n className=\"button--primary button--kiosk\"\n >\n <i className=\"fa fa-video-camera\" />\n <strong>\n {CommaAuth.isAuthenticated()\n ? 'Find a drive in Explorer'\n : 'Log in with Explorer'}\n </strong>\n <sup>Click \"View CAN Data\" while replaying a drive</sup>\n </button>\n );\n }\n\n renderOnboardingOptions() {\n return (\n <div className=\"cabana-onboarding-modes\">\n <div className=\"cabana-onboarding-mode\">{this.renderLogin()}</div>\n <div className=\"cabana-onboarding-mode\">\n <button\n className={cx('button--secondary button--kiosk', {\n 'is-disabled':\n !this.state.webUsbEnabled\n || this.props.attemptingPandaConnection\n })}\n onClick={this.attemptPandaConnection}\n >\n <i className=\"fa fa-bolt\" />\n <strong>Launch Realtime Streaming</strong>\n <sup>\n Interactively stream car data over USB with\n {' '}\n <em>panda</em>\n </sup>\n {this.renderPandaEligibility()}\n </button>\n </div>\n </div>\n );\n }\n\n renderUsbInstructions() {\n return (\n <div className=\"cabana-onboarding-instructions\">\n <button\n className=\"button--small button--inverted\"\n onClick={this.toggleUsbInstructions}\n >\n <i className=\"fa fa-chevron-left\" />\n <span> Go back</span>\n </button>\n <h3>Follow these directions to enable WebUSB:</h3>\n <ol className=\"cabana-onboarding-instructions-list list--bubbled\">\n <li>\n <p>\n <strong>Open your Chrome settings:</strong>\n </p>\n <div className=\"inset\">\n <span>\n chrome://flags/#enable-experimental-web-platform-features\n </span>\n </div>\n </li>\n <li>\n <p>\n <strong>Enable Experimental Platform features:</strong>\n </p>\n <img\n alt=\"Screenshot of Google Chrome Experimental Platform features\"\n src={OnboardingModal.instructionalImages.step2}\n />\n </li>\n <li>\n <p>\n <strong>Enable WebUSB:</strong>\n </p>\n <img\n alt=\"Screenshot of Google Chrome enable WebUSB\"\n src={OnboardingModal.instructionalImages.step3}\n />\n </li>\n <li>\n <p>\n <strong>\n Relaunch your Chrome browser and try enabling live mode again.\n </strong>\n </p>\n </li>\n </ol>\n </div>\n );\n }\n\n renderModalContent() {\n if (this.state.viewingUsbInstructions) {\n return this.renderUsbInstructions();\n }\n return this.renderOnboardingOptions();\n }\n\n renderModalFooter() {\n return (\n <p>\n <span>\n Don't have a\n {' '}\n <a\n href=\"https://panda.comma.ai\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n panda\n </a>\n ?\n {' '}\n </span>\n <span>\n <a\n href=\"https://panda.comma.ai\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Get one here\n </a>\n {' '}\n </span>\n <span>\n or\n {' '}\n <a href={`${window.location.href}?demo=1`}>try the demo</a>\n.\n </span>\n </p>\n );\n }\n\n render() {\n return (\n <Modal\n title=\"Welcome to Cabana\"\n subtitle=\"Get started by selecting a drive from Explorer or enabling live mode\"\n footer={this.renderModalFooter()}\n disableClose\n variations={['wide', 'dark']}\n >\n {this.renderModalContent()}\n </Modal>\n );\n }\n}\n","import React, { Component } from 'react';\nimport cx from 'classnames';\nimport PropTypes from 'prop-types';\nimport FileSaver from 'file-saver';\n\nimport OpenDbc from '../api/OpenDbc';\nimport DBC from '../models/can/dbc';\nimport Modal from './Modals/baseModal';\n// import TabStyles from '../styles/modal-tabs';\n\nexport default class SaveDbcModal extends Component {\n static propTypes = {\n dbc: PropTypes.instanceOf(DBC).isRequired,\n sourceDbcFilename: PropTypes.string.isRequired,\n handleClose: PropTypes.func.isRequired,\n onDbcSaved: PropTypes.func.isRequired,\n openDbcClient: PropTypes.instanceOf(OpenDbc).isRequired,\n hasGithubAuth: PropTypes.bool.isRequired,\n loginWithGithub: PropTypes.element.isRequired\n };\n\n constructor(props) {\n super(props);\n this.state = {\n tab: 'GitHub',\n openDbcFork: null,\n dbcFilename: this.props.sourceDbcFilename,\n tabs: ['GitHub', 'Download'],\n commitMessage: 'OpenDBC updates'\n };\n\n this.commitToGitHub = this.commitToGitHub.bind(this);\n this.downloadDbcFile = this.downloadDbcFile.bind(this);\n this.forkOpenDbcAndWait = this.forkOpenDbcAndWait.bind(this);\n this.renderForkButton = this.renderForkButton.bind(this);\n this.renderTabNavigation = this.renderTabNavigation.bind(this);\n this.renderActions = this.renderActions.bind(this);\n }\n\n async componentWillMount() {\n const openDbcFork = await this.props.openDbcClient.getUserOpenDbcFork();\n this.setState({ openDbcFork });\n }\n\n async commitToGitHub() {\n const { openDbcFork, dbcFilename } = this.state;\n const filename = `${dbcFilename.replace(/\\.dbc/g, '')}.dbc`;\n const success = await this.props.openDbcClient.commitFile(\n openDbcFork,\n filename,\n this.props.dbc.text(),\n this.state.commitMessage\n );\n if (success) {\n this.props.onDbcSaved(filename);\n }\n }\n\n async downloadDbcFile() {\n const blob = new Blob([this.props.dbc.text()], {\n type: 'text/plain;charset=utf-8'\n });\n const filename = `${this.state.dbcFilename.replace(/\\.dbc/g, '')}.dbc`;\n FileSaver.saveAs(blob, filename, true);\n }\n\n async forkOpenDbcAndWait() {\n const forkResponseSuccess = await this.props.openDbcClient.fork();\n if (forkResponseSuccess) {\n let isTimedOut = false;\n const timeout = window.setTimeout(() => {\n isTimedOut = true;\n }, 30000);\n\n const interval = window.setInterval(() => {\n if (!isTimedOut) {\n this.props.openDbcClient.getUserOpenDbcFork().then((openDbcFork) => {\n if (openDbcFork !== null) {\n this.setState({ openDbcFork });\n window.clearInterval(interval);\n window.clearTimeout(timeout);\n }\n });\n } else {\n window.clearInterval(interval);\n }\n }, 3000);\n } else {\n // fork failed\n }\n }\n\n primaryActionDisabled() {\n const { tab } = this.state;\n if (tab === 'GitHub') {\n return (\n this.state.openDbcFork != null && this.state.dbcFilename.length > 0\n );\n }\n if (tab === 'Download') {\n return true;\n }\n }\n\n renderForkButton() {\n return (\n <button onClick={this.forkOpenDbcAndWait}>\n <i className=\"fa fa-code-fork\" />\n <span> Fork OpenDBC</span>\n </button>\n );\n }\n\n renderForkStep() {\n const { openDbcFork } = this.state;\n let content;\n if (openDbcFork !== null) {\n content = (\n <button disabled>\n <i className=\"fa fa-code-fork\" />\n <span>\n {' '}\n Forked:\n {openDbcFork}\n </span>\n </button>\n );\n } else if (this.props.hasGithubAuth) {\n content = this.renderForkButton();\n } else {\n content = this.props.loginWithGithub;\n }\n return (\n <div>\n {openDbcFork !== null ? this.renderForkButton() : null}\n {content}\n <hr />\n </div>\n );\n }\n\n renderFilenameField() {\n return (\n <div className=\"form-field\" data-extension=\".dbc\">\n <label htmlFor=\"filename\">\n <span>Choose a filename:</span>\n <sup>Pick a unique name for your car DBC file</sup>\n </label>\n <input\n type=\"text\"\n id=\"filename\"\n value={this.state.dbcFilename.replace(/\\.dbc/g, '')}\n size={this.state.dbcFilename.length + 2}\n onChange={(e) => this.setState({ dbcFilename: e.target.value })}\n />\n </div>\n );\n }\n\n renderTabNavigation() {\n return (\n <div className=\"cabana-tabs-navigation\">\n {this.state.tabs.map((tab) => (\n <a\n className={cx({ 'is-active': this.state.tab === tab })}\n onClick={() => {\n this.setState({ tab });\n }}\n key={tab}\n >\n <span>{tab}</span>\n </a>\n ))}\n </div>\n );\n }\n\n renderCommitMessage() {\n return (\n <div className=\"form-field\">\n <label htmlFor=\"commit-message\">\n <span>Commit Message:</span>\n <sup>Message appears in git logs</sup>\n </label>\n <input\n type=\"text\"\n id=\"commit-message\"\n value={this.state.commitMessage}\n onChange={(e) => this.setState({ commitMessage: e.target.value })}\n />\n </div>\n );\n }\n\n renderTabContent() {\n const { tab } = this.state;\n if (tab === 'GitHub') {\n return (\n <div>\n {this.renderForkStep()}\n {this.renderFilenameField()}\n {this.renderCommitMessage()}\n </div>\n );\n }\n if (tab === 'Download') {\n return <div>{this.renderFilenameField()}</div>;\n }\n }\n\n renderActions() {\n const { tab } = this.state;\n if (tab === 'GitHub') {\n return (\n <div>\n <button className=\"button--inverted\" onClick={this.props.handleClose}>\n <span>Cancel</span>\n </button>\n <button className=\"button--primary\" onClick={this.commitToGitHub}>\n <span>Commit to GitHub</span>\n </button>\n </div>\n );\n }\n if (tab === 'Download') {\n return (\n <div>\n <button className=\"button--inverted\" onClick={this.props.handleClose}>\n <span>Cancel</span>\n </button>\n <button className=\"button--primary\" onClick={this.downloadDbcFile}>\n <span>Download</span>\n </button>\n </div>\n );\n }\n }\n\n render() {\n return (\n <Modal\n title=\"Save DBC File\"\n subtitle=\"Save your progress and output to a DBC file\"\n handleClose={this.props.handleClose}\n navigation={this.renderTabNavigation()}\n actions={this.renderActions()}\n >\n {this.renderTabContent()}\n </Modal>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nimport Modal from './Modals/baseModal';\n\nexport default class EditMessageModal extends Component {\n static propTypes = {\n handleClose: PropTypes.func.isRequired,\n handleSave: PropTypes.func.isRequired,\n message: PropTypes.object.isRequired\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n messageFrame: props.message.frame.copy()\n };\n this.handleSave = this.handleSave.bind(this);\n this.editTransmitter = this.editTransmitter.bind(this);\n this.addTransmitter = this.addTransmitter.bind(this);\n this.renderActions = this.renderActions.bind(this);\n }\n\n handleSave() {\n this.props.handleSave(this.state.messageFrame);\n }\n\n addTransmitter() {\n const { messageFrame } = this.state;\n messageFrame.addTransmitter();\n this.setState({ messageFrame });\n }\n\n editTransmitter(transmitter) {}\n\n renderActions() {\n return (\n <div>\n <button className=\"button--inverted\" onClick={this.props.handleClose}>\n Cancel\n </button>\n <button className=\"button--primary\" onClick={this.handleSave}>\n Save Message\n </button>\n </div>\n );\n }\n\n render() {\n return (\n <Modal\n title={`Edit Message: (${this.props.message.id})`}\n subtitle=\"Make changes and update defaults of this message\"\n handleClose={this.props.handleClose}\n handleSave={this.handleSave}\n actions={this.renderActions()}\n >\n <div className=\"form-field\">\n <label htmlFor=\"message_name\">\n <span>Name</span>\n <sup>Customize the name of this message</sup>\n </label>\n <input\n type=\"text\"\n id=\"message_name\"\n value={this.state.messageFrame.name}\n onChange={(e) => {\n const { messageFrame } = this.state;\n messageFrame.name = e.target.value;\n this.setState({ messageFrame });\n }}\n />\n </div>\n <div className=\"form-field\">\n <label htmlFor=\"message_size\">\n <span>Size</span>\n <sup>Add a size parameter to this message</sup>\n </label>\n <input\n type=\"number\"\n id=\"message_size\"\n value={this.state.messageFrame.size}\n onChange={(e) => {\n const { messageFrame } = this.state;\n if (e.target.value > 8) {\n return;\n }\n messageFrame.size = parseInt(e.target.value, 10);\n this.setState({ messageFrame });\n }}\n />\n </div>\n <div className=\"form-field u-hidden\">\n <label htmlFor=\"message_transmitters\">\n <span>Transmitters</span>\n <sup>\n Add the physical ECU units that this message is coming from.\n </sup>\n </label>\n <div className=\"form-field-inset\">\n <ul className=\"form-field-inset-list\">\n {this.state.messageFrame.transmitters.map((transmitter) => (\n <li className=\"form-field-inset-list-item\" key={transmitter}>\n <div className=\"form-field-inset-list-item-title\">\n <span>{transmitter}</span>\n </div>\n <div className=\"form-field-inset-list-item-action\">\n <button className=\"button--tiny button--alpha\">Edit</button>\n </div>\n </li>\n ))}\n <button className=\"button--tiny button--alpha\">\n <span>\n <i className=\"fa fa-plus\" />\n {' '}\nAdd Transmitter\n </span>\n </button>\n </ul>\n </div>\n </div>\n </Modal>\n );\n }\n}\n","import styled, { keyframes } from 'react-emotion';\n\nconst frames = keyframes`\n 0% {\n transform: translateX(0)\n }\n to {\n transform: translateX(-400px)\n }\n`;\nconst animationColor1 = 'rgba(74, 242, 161, 1.00)';\nconst animationColor2 = 'rgba(140, 169, 197, 1.00)';\n\nexport default styled('div')`\n display: block;\n animation-name: ${frames};\n animation-duration: 2s;\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n background-color: ${animationColor1};\n background-image: linear-gradient(\n to right,\n ${animationColor2} 0,\n ${animationColor2} 50%,\n ${animationColor1} 50%,\n ${animationColor1} 100%\n );\n background-repeat: repeat-x;\n background-size: 25pc 25pc;\n width: 200%;\n position: fixed;\n top: 0;\n left: 0;\n height: 2;\n`;\n","import SocketIO from 'socket.io-client';\nimport { UNLOGGER_HOST } from '../config';\n\nexport default class UnloggerClient {\n constructor() {\n this.socket = SocketIO(UNLOGGER_HOST);\n }\n\n seek(dongleId, baseTime, seekSeconds) {\n this.socket.emit('seek', dongleId, baseTime, seekSeconds);\n }\n}\n","export function hash(str) {\n let hash = 5381;\n let i = str.length;\n\n while (i) {\n hash = (hash * 33) ^ str.charCodeAt(--i);\n }\n\n // to positive number\n return (hash >>> 0).toString(16);\n}\n","import Moment from 'moment';\nimport CorollaDBC from './corolla-dbc';\nimport DBC from './models/can/dbc';\nimport {\n fetchPersistedDbc,\n fetchPersistedGithubAuthToken,\n persistGithubAuthToken\n } from './api/localstorage';\n\nexport async function loadRetropilotDrive(retropilotHost, driveIdentifier, seekTime) {\n if (driveIdentifier==null || driveIdentifier.length==0) {\n global.retropilotLoaded=false;\n return;\n }\n\n const response = await fetch(retropilotHost+'useradmin/cabana_drive/'+encodeURIComponent(driveIdentifier));\n try {\n var retropilotDrive = await response.json();\n } catch (exception) {}\n\n if (retropilotDrive==undefined || retropilotDrive.logUrls==undefined) {\n alert(retropilotDrive!=undefined && retropilotDrive.status!=undefined ? retropilotDrive.status : 'fetching retropilot drive failed!');\n global.retropilotLoaded=false;\n return;\n }\n global.retropilotLogUrls = retropilotDrive.logUrls;\n\n const dbcObj = retropilotDrive.dbc!=undefined && retropilotDrive.dbc.length>0 ? new DBC(retropilotDrive.dbc) : CorollaDBC;\n\n global.retropilotProps = {\n autoplay: true,\n startTime: seekTime,\n segments : global.retropilotLogUrls.length,\n isDemo : true,\n max: global.retropilotLogUrls.length,\n name: retropilotDrive.driveIdentifier,\n dongleId: retropilotDrive.dongleId,\n dbc: dbcObj,\n isDemo: true,\n dbcFilename: retropilotDrive.dbcFilename!=undefined ? retropilotDrive.dbcFilename : 'toyota_nodsu_pt_generated.dbc' \n };\n\n global.retropilotRoute = {\n fullname: retropilotDrive.name,\n proclog: global.retropilotProps.max,\n start_time: Moment(global.retropilotProps.name, 'YYYY-MM-DD--H-m-s'),\n url: retropilotDrive.driveUrl\n };\n\n\n if (global.retropilotProps.max>0) {\n let persistedDbc = fetchPersistedDbc(global.retropilotRoute.fullname);\n if (persistedDbc) {\n const { dbcFilename, dbc } = persistedDbc;\n global.retropilotProps.dbc = dbc;\n global.retropilotProps.dbcFilename = dbcFilename;\n }\n\n global.retropilotLoaded=true;\n }\n else\n global.retropilotLoaded=false;\n\n};","function elementWiseEquals(arr1, arr2) {\n return (\n arr1.length === arr2.length && arr1.every((ele, idx) => arr2[idx] === ele)\n );\n}\n\nfunction findIndexRight(arr, condition) {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (condition(arr[i])) {\n return i;\n }\n }\n}\n\nexport default { elementWiseEquals, findIndexRight };\n","import ArrayUtils from '../utils/array';\nimport { CAN_GRAPH_MAX_POINTS } from '../config';\n\nfunction signalColors(signal, msg) {\n return signal.colors.map((v) => (v ^ msg.address) ^ msg.bus);\n}\n\nfunction _calcGraphData(msg, signalUid, firstCanTime) {\n if (!msg) return null;\n\n const signal = Object.values(msg.frame.signals).find(\n (s) => s.uid === signalUid\n );\n if (!signal) {\n console.warn('_calcGraphData: no signal', signalUid, msg);\n return null;\n }\n let samples = [];\n const skip = Math.floor(msg.entries.length / CAN_GRAPH_MAX_POINTS);\n\n if (skip === 0) {\n samples = msg.entries;\n } else {\n for (let i = 0; i < msg.entries.length; i += skip) {\n samples.push(msg.entries[i]);\n }\n // Always include last message entry, which faciliates graphData comparison\n samples.push(msg.entries[msg.entries.length - 1]);\n }\n if (!samples.length) {\n return [];\n }\n\n const colors = signal.getColors(msg.id);\n signalUid = msg.id + signalUid;\n // sorting these doesn't fix the phantom lines\n let lastEntry = samples[0].relTime;\n return samples\n .filter((e) => e.signals[signal.name] !== undefined)\n .map((entry) => {\n if (entry.relTime < lastEntry) {\n console.log(msg);\n console.error('Found out of order messages');\n debugger;\n }\n if (entry.relTime - lastEntry > 2) {\n signalUid = Math.random().toString(36);\n }\n lastEntry = entry.relTime;\n // console.log(entry.relTime - lastEntry);\n return {\n x: entry.time,\n relTime: entry.relTime,\n y: entry.signals[signal.name],\n unit: signal.unit,\n color: `rgba(${colors.join(',')}, 0.5)`,\n signalName: signal.name,\n signalUid\n };\n });\n}\n\nfunction appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {\n const messagesPerPlot = plottedSignals.map((plottedMessages) => plottedMessages.reduce((messages, { messageId, signalUid }) => {\n messages.push(messageId);\n return messages;\n }, []));\n\n const extendedPlots = messagesPerPlot\n .map((plottedMessageIds, index) => ({ plottedMessageIds, index })) // preserve index so we can look up graphData\n .filter(({ plottedMessageIds, index }) => {\n if (index < graphData.length) {\n let maxGraphTime = 0;\n const { series } = graphData[index];\n if (series.length > 0) {\n maxGraphTime = series[graphData[index].series.length - 1].relTime;\n }\n\n return plottedMessageIds.some(\n (messageId) => (messages[messageId].entries.length > 0 && series.length === 0)\n || messages[messageId].entries.some((e) => e.relTime > maxGraphTime)\n );\n }\n return false;\n })\n .map(({ plottedMessageIds, index }) => {\n plottedMessageIds = plottedMessageIds.reduce((arr, messageId) => {\n if (arr.indexOf(messageId) === -1) {\n arr.push(messageId);\n }\n return arr;\n }, []);\n return { plottedMessageIds, index };\n });\n\n extendedPlots.forEach(({ plottedMessageIds, index }) => {\n const signalUidsByMessageId = plottedSignals[index].reduce(\n (obj, { messageId, signalUid }) => {\n if (!obj[messageId]) {\n obj[messageId] = [];\n }\n obj[messageId].push(signalUid);\n return obj;\n },\n {}\n );\n const { series } = graphData[index];\n const graphDataMaxMessageTimes = plottedMessageIds.reduce(\n (obj, messageId) => {\n const signalUids = signalUidsByMessageId[messageId];\n const maxIndex = ArrayUtils.findIndexRight(\n series,\n (entry) => signalUids.indexOf(entry.signalUid) !== -1\n );\n if (maxIndex) {\n obj[messageId] = series[maxIndex].relTime;\n } else if (series.length > 0) {\n obj[messageId] = series[series.length - 1].relTime;\n } else {\n // Graph data is empty\n obj[messageId] = -1;\n }\n\n return obj;\n },\n {}\n );\n\n let newGraphData = [];\n plottedMessageIds\n .map((messageId) => ({ messageId, entries: messages[messageId].entries }))\n .filter(\n (\n { messageId, entries } // Filter to only messages with stale graphData\n ) => entries[entries.length - 1].relTime\n > graphDataMaxMessageTimes[messageId]\n )\n .forEach(({ messageId, entries }) => {\n // Compute and append new graphData\n const firstNewEntryIdx = entries.findIndex(\n (entry) => entry.relTime > graphDataMaxMessageTimes[messageId]\n );\n\n const newEntries = entries.slice(firstNewEntryIdx);\n signalUidsByMessageId[messageId].forEach((signalUid) => {\n const signalGraphData = _calcGraphData(\n {\n ...messages[messageId],\n entries: newEntries\n },\n signalUid,\n firstCanTime\n );\n\n newGraphData = newGraphData.concat(signalGraphData);\n });\n });\n\n const messageIdOutOfBounds = series.length > 0\n && plottedMessageIds.find(\n (messageId) => messages[messageId].entries.length > 0\n && series[0].relTime < messages[messageId].entries[0].relTime\n );\n graphData[index] = {\n series: graphData[index].series.concat(newGraphData),\n updated: Date.now()\n };\n\n if (messageIdOutOfBounds) {\n const graphDataLowerBound = graphData[index].series.findIndex(\n (e) => e.relTime > messages[messageIdOutOfBounds].entries[0].relTime\n );\n\n if (graphDataLowerBound) {\n graphData[index].series = graphData[index].series.slice(\n graphDataLowerBound\n );\n }\n }\n });\n\n return [...graphData];\n}\n\nexport default { _calcGraphData, appendNewGraphData, signalColors };\n","export default {\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"width\": 400,\n \"height\": 200,\n \"padding\": {\n \"top\": 5,\n \"left\": 30,\n \"right\": 5,\n \"bottom\": 10\n },\n \"data\": [\n {\n \"name\": \"table\"\n },\n {\n \"name\": \"segment\"\n },\n {\n \"name\": \"tooltip\",\n \"source\": \"table\",\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"abs(datum.relTime - tipTime) <= 0.05\"\n },\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"color\"],\n \"fields\": [\n \"relTime\",\n \"y\",\n \"unit\"\n ],\n \"ops\": [\n \"min\",\n \"argmin\",\n \"argmin\"\n ],\n \"as\": [\n \"min\",\n \"argmin\",\n \"argmin\"\n ]\n }\n ]\n },\n {\n \"name\": \"ySegmentScale\",\n \"source\": \"table\",\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"length(segment) != 2 || (datum.relTime >= segment[0] && datum.relTime <= segment[1])\"\n },\n {\n \"type\": \"extent\",\n \"field\": \"y\",\n \"signal\": \"ySegment\"\n }\n ]\n }\n ],\n\n \"scales\": [\n {\n \"name\": \"xscale\",\n \"type\": \"linear\",\n \"range\": \"width\",\n \"domain\": {\n \"data\": \"table\",\n \"field\": \"x\"\n },\n \"zero\": false\n },\n {\n \"name\": \"xrelscale\",\n \"type\": \"linear\",\n \"range\": \"width\",\n \"domain\": {\n \"data\": \"table\",\n \"field\": \"relTime\"\n },\n \"zero\": false,\n \"clamp\": true,\n \"nice\": true,\n \"domainRaw\": {\n \"signal\": \"segment\"\n }\n },\n {\n \"name\": \"yscale\",\n \"type\": \"linear\",\n \"range\": \"height\",\n \"clamp\": true,\n \"zero\": false,\n \"nice\": true,\n \"domain\": {\n \"signal\": \"ySegment\"\n }\n },\n {\n \"name\": \"color\",\n \"type\": \"ordinal\",\n \"domain\": {\n \"data\": \"table\",\n \"field\": \"color\"\n },\n \"range\": {\n \"data\": \"table\",\n \"field\": \"color\"\n }\n }\n ],\n\n\n \"axes\": [\n {\n \"orient\": \"bottom\",\n \"scale\": \"xrelscale\",\n \"labelOverlap\": true\n },\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\"\n }\n ],\n\n \"signals\": [\n {\n \"name\": \"tipTime\",\n \"on\": [\n {\n \"events\": \"mousemove\",\n \"update\": \"invert('xrelscale', x())\"\n },\n {\n \"events\": \"mouseout\",\n \"update\": \"null\"\n }\n ]\n },\n {\n \"name\": \"clickTime\",\n \"on\": [\n {\n \"events\": \"click\",\n \"update\": \"invert('xrelscale', x())\"\n }\n ]\n },\n {\n \"name\": \"videoTime\"\n },\n {\n \"name\": \"segment\",\n \"value\": {\n \"data\": \"table\",\n \"field\": \"relTime\"\n }\n }\n ],\n\n \"marks\": [\n {\n \"type\": \"group\",\n \"name\": \"plot\",\n \"interactive\": true,\n \"encode\": {\n \"enter\": {\n \"width\": {\n \"signal\": \"width\"\n },\n \"height\": {\n \"signal\": \"height\"\n },\n \"fill\": {\n \"value\": \"transparent\"\n }\n }\n },\n \"signals\": [\n {\n \"name\": \"brush\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@boundingRect:mousedown\",\n \"update\": \"[x(), x()]\"\n },\n {\n \"events\": \"[@boundingRect:mousedown, window:mouseup] > window:mousemove!\",\n \"update\": \"[brush[0], clamp(x(), 0, width)]\"\n },\n {\n \"events\": {\n \"signal\": \"delta\"\n },\n \"update\": \"clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)\"\n }\n ]\n },\n {\n \"name\": \"anchor\",\n \"value\": null,\n \"on\": [\n {\n \"events\": \"@brush:mousedown\",\n \"update\": \"slice(brush)\"\n }\n ]\n },\n {\n \"name\": \"xdown\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@brush:mousedown\",\n \"update\": \"x()\"\n }\n ]\n },\n {\n \"name\": \"xup\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@brush:mouseup\",\n \"update\": \"x()\"\n }\n ]\n },\n {\n \"name\": \"delta\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"[@brush:mousedown, window:mouseup] > window:mousemove!\",\n \"update\": \"x() - xdown\"\n }\n ]\n },\n {\n \"name\": \"segment\",\n \"push\": \"outer\",\n \"on\": [\n {\n \"events\": \"window:mouseup\",\n \"update\": \"span(brush) && span(brush) > 15 ? invert('xrelscale', brush) : segment\"\n }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"group\",\n \"from\": {\n \"facet\": {\n \"name\": \"series\",\n \"data\": \"table\",\n \"groupby\": \"signalUid\"\n }\n },\n \"marks\": [{\n \"type\": \"line\",\n \"name\": \"lineMark\",\n \"from\": {\n \"data\": \"series\"\n },\n \"interactive\": true,\n \"encode\": {\n \"update\": {\n \"value\": \"natural\",\n \"tension\": 0,\n \"x\": {\n \"scale\": \"xrelscale\",\n \"field\": \"relTime\"\n },\n \"y\": {\n \"scale\": \"yscale\",\n \"field\": \"y\"\n },\n \"detail\": {\n \"field\": \"signalUid\"\n }\n },\n \"hover\": {\n \"fillOpacity\": {\n \"value\": 0.5\n }\n },\n \"enter\": {\n \"clip\": {\n \"value\": true\n },\n \"stroke\": {\n \"scale\": \"color\",\n \"field\": \"color\"\n },\n \"strokeWidth\": {\n \"value\": 2\n }\n }\n }\n }]\n },\n {\n \"type\": \"rect\",\n \"interactive\": true,\n \"name\": \"brush\",\n \"encode\": {\n \"enter\": {\n \"y\": {\n \"value\": 0\n },\n \"height\": {\n \"signal\": \"height\"\n },\n \"fill\": {\n \"value\": \"#333\"\n },\n \"fillOpacity\": {\n \"value\": 0.2\n }\n },\n \"update\": {\n \"x\": {\n \"signal\": \"brush[0]\"\n },\n \"x2\": {\n \"signal\": \"brush[1]\"\n }\n }\n }\n },\n {\n \"type\": \"rule\",\n \"encode\": {\n \"update\": {\n \"y\": {\n \"value\": 0\n },\n \"y2\": {\n \"field\": {\n \"group\": \"height\"\n }\n },\n \"stroke\": {\n \"value\": \"#000\"\n },\n \"strokeWidth\": {\n \"value\": 2\n },\n \"x\": {\n \"scale\": \"xrelscale\",\n \"signal\": \"videoTime\",\n \"offset\": 0.5\n }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"tooltip\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"scale\": \"xrelscale\",\n \"field\": \"argmin.relTime\"\n },\n \"y\": {\n \"scale\": \"yscale\",\n \"field\": \"argmin.y\"\n },\n \"size\": {\n \"value\": 50\n },\n \"fill\": {\n \"value\": \"black\"\n }\n }\n }\n },\n {\n \"type\": \"group\",\n \"from\": {\n \"data\": \"tooltip\"\n },\n \"interactive\": false,\n \"name\": \"tooltipGroup\",\n \"encode\": {\n \"update\": {\n \"x\": [\n {\n \"test\": \"inrange(datum.argmin.relTime + 80, domain('xrelscale'))\",\n \"scale\": \"xrelscale\",\n \"field\": \"argmin.relTime\"\n },\n {\n \"scale\": \"xrelscale\",\n \"field\": \"argmin.relTime\",\n \"offset\": -80\n }\n ],\n \"y\": {\n \"scale\": \"yscale\",\n \"field\": \"argmin.y\"\n },\n \"height\": {\n \"value\": 20\n },\n \"width\": {\n \"value\": 80\n },\n \"fill\": {\n \"value\": \"#fff\"\n },\n \"fillOpacity\": {\n \"value\": 0.85\n },\n \"stroke\": {\n \"value\": \"#aaa\"\n },\n \"strokeWidth\": {\n \"value\": 0.5\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"text\": {\n \"signal\": \"format(parent.argmin.relTime, ',.2f') + ': ' + format(parent.argmin.y, ',.2f') + ' ' + parent.argmin.unit\"\n },\n \"fill\": {\n \"value\": \"black\"\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"y\": {\n \"value\": 20\n }\n }\n }\n }\n ]\n },\n {\n \"type\": \"rect\",\n \"name\": \"boundingRect\",\n \"interactive\": true,\n \"encode\": {\n \"enter\": {\n \"width\": {\n \"signal\": \"width\"\n },\n \"height\": {\n \"signal\": \"height\"\n },\n \"fill\": {\n \"value\": \"transparent\"\n }\n }\n }\n }\n ]\n }\n ]\n};\n","import React, { Component } from 'react';\nimport Measure from 'react-measure';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\nimport { Vega } from 'react-vega';\n\nimport Signal from '../models/can/signal';\nimport GraphData from '../models/graph-data';\nimport CanPlotSpec from '../vega/CanPlot';\nimport debounce from '../utils/debounce';\n\nconst DefaultPlotInnerStyle = {\n position: 'absolute',\n top: 0,\n left: 0\n};\n\nexport default class CanGraph extends Component {\n static emptyTable = [];\n\n static propTypes = {\n plottedSignal: PropTypes.string,\n messages: PropTypes.object,\n messageId: PropTypes.string,\n messageName: PropTypes.string,\n signalSpec: PropTypes.instanceOf(Signal),\n segment: PropTypes.array,\n unplot: PropTypes.func,\n onRelativeTimeClick: PropTypes.func,\n currentTime: PropTypes.number,\n onSegmentChanged: PropTypes.func,\n onDragStart: PropTypes.func,\n onDragEnd: PropTypes.func,\n container: PropTypes.node,\n dragPos: PropTypes.object,\n canReceiveGraphDrop: PropTypes.bool,\n onGraphRefAvailable: PropTypes.func,\n plottedSignals: PropTypes.array\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n plotInnerStyle: null,\n shiftX: 0,\n shiftY: 0,\n bounds: null,\n isDataInserted: false,\n data: this.getGraphData(props),\n spec: this.getGraphSpec(props)\n };\n this.onNewView = this.onNewView.bind(this);\n this.onSignalClickTime = this.onSignalClickTime.bind(this);\n this.onSignalSegment = this.onSignalSegment.bind(this);\n this.onDragAnchorMouseDown = this.onDragAnchorMouseDown.bind(this);\n this.onDragAnchorMouseUp = this.onDragAnchorMouseUp.bind(this);\n this.onDragStart = this.onDragStart.bind(this);\n this.onPlotResize = this.onPlotResize.bind(this);\n this.insertData = this.insertData.bind(this);\n }\n\n getGraphData(props) {\n let firstRelTime = -1;\n let lastRelTime = -1;\n const series = props.plottedSignals\n .map((signals) => {\n const { messageId, signalUid } = signals;\n const { entries } = props.messages[messageId];\n if (entries.length) {\n let messageRelTime = entries[0].relTime;\n if (firstRelTime === -1) {\n firstRelTime = messageRelTime;\n } else {\n firstRelTime = Math.min(firstRelTime, messageRelTime);\n }\n messageRelTime = entries[entries.length - 1].relTime;\n lastRelTime = Math.max(lastRelTime, messageRelTime);\n }\n return GraphData._calcGraphData(\n props.messages[messageId],\n signalUid,\n 0\n );\n })\n .reduce((m, v) => m.concat(v), []);\n\n return {\n updated: Date.now(),\n series,\n firstRelTime,\n lastRelTime\n };\n }\n\n getGraphSpec(props) {\n return {\n ...CanPlotSpec,\n scales: [\n {\n ...CanPlotSpec.scales[0],\n domainMin: props.segment[0],\n domainMax: props.segment[1]\n },\n ...CanPlotSpec.scales.slice(1)\n ]\n };\n }\n\n segmentIsNew(newSegment) {\n return (\n newSegment.length !== this.props.segment.length\n || !newSegment.every((val, idx) => this.props.segment[idx] === val)\n );\n }\n\n visualChanged(prevProps, nextProps) {\n return (\n prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop\n || JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos)\n );\n }\n\n onPlotResize(options) {\n if (!this.view) {\n return;\n }\n\n let bounds = null;\n if (options && options.bounds) {\n this.setState({ bounds: options.bounds });\n bounds = options.bounds;\n } else {\n bounds = this.state.bounds;\n }\n\n this.view.runAfter(this.updateBounds);\n }\n\n updateBounds = debounce(() => {\n this.view.signal('width', this.state.bounds.width - 70);\n this.view.signal('height', 0.4 * (this.state.bounds.width - 70)); // 5:2 aspect ratio\n this.view.run();\n }, 100);\n\n insertData = debounce(() => {\n if (!this.view) {\n console.log('Cannot insertData');\n return;\n }\n\n // adding plot points by diff isn't faster since it basically has to be n^2\n // out-of-order events make it so that you can't just check the bounds\n const { series } = this.state.data;\n const changeset = this.view\n .changeset()\n .remove((v) => true)\n .insert(series);\n this.view.change('table', changeset);\n this.view.run();\n }, 250);\n\n componentWillReceiveProps(nextProps) {\n if (\n nextProps.dragPos\n && JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos)\n ) {\n this.updateStyleFromDragPos(nextProps.dragPos);\n } else if (!nextProps.dragPos && this.state.plotInnerStyle !== null) {\n this.setState({ plotInnerStyle: null });\n }\n if (\n this.props.messages !== nextProps.messages\n || this.props.plottedSignal !== nextProps.plottedSignal\n ) {\n console.log('Calculating new data!');\n const data = this.getGraphData(nextProps);\n // if (\n // data.series.length === this.state.data.series.length\n // && data.firstRelTime === this.state.data.firstRelTime\n // && data.lastRelTime === this.state.data.lastRelTime\n // && JSON.stringify(nextProps.signalSpec) === JSON.stringify(this.props.signalSpec)\n // ) {\n // // do nothing, the data didn't *actually* change\n // } else {\n console.log('Inserting new data!');\n this.setState({ data });\n // }\n }\n if (this.segmentIsNew(nextProps.segment)) {\n this.setState({ spec: this.getGraphSpec(nextProps) });\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n if (!this.view) {\n return true;\n }\n if (this.state.spec !== nextState.spec) {\n return true;\n }\n if (this.state.data !== nextState.data) {\n this.insertData();\n }\n if (this.props.currentTime !== nextProps.currentTime) {\n this.view.signal('videoTime', nextProps.currentTime);\n }\n if (this.segmentIsNew(nextProps.segment)) {\n if (nextProps.segment.length > 0) {\n // Set segmented domain\n this.view.signal('segment', nextProps.segment);\n } else {\n // Reset segment to full domain\n this.view.signal('segment', 0);\n }\n }\n this.view.runAsync();\n return false;\n }\n\n componentDidUpdate(oldProps, oldState) {\n if (this.view) {\n if (this.props.segment.length > 0) {\n // Set segmented domain\n this.view.signal('segment', this.props.segment);\n } else {\n // Reset segment to full domain\n this.view.signal('segment', 0);\n }\n this.view.signal('videoTime', this.props.currentTime);\n this.view.runAsync();\n }\n }\n\n updateStyleFromDragPos({ left, top }) {\n const plotInnerStyle = { ...this.state.plotInnerStyle };\n plotInnerStyle.left = left;\n plotInnerStyle.top = top;\n this.setState({ plotInnerStyle });\n }\n\n onNewView(view) {\n this.view = view;\n\n if (this.state.bounds) {\n this.onPlotResize();\n }\n if (this.props.segment.length > 0) {\n view.signal('segment', this.props.segment);\n }\n view.signal('videoTime', this.props.currentTime);\n\n this.insertData();\n }\n\n onSignalClickTime(signal, clickTime) {\n // console.log('onSignalClickTime', signal, clickTime);\n if (clickTime !== undefined) {\n this.props.onRelativeTimeClick(this.props.messageId, clickTime);\n }\n }\n\n onSignalSegment(signal, segment) {\n // console.log('onSignalSegment', signal, segment);\n if (!Array.isArray(segment)) {\n return;\n }\n\n this.props.onSegmentChanged(this.props.messageId, segment);\n\n if (!this.view) {\n return;\n }\n\n this.view.runAfter(() => {\n const state = this.view.getState();\n state.subcontext[0].signals.brush = 0;\n this.view.setState(state);\n this.insertData();\n });\n }\n\n plotInnerStyleFromMouseEvent(e) {\n const { shiftX, shiftY } = this.state;\n const plotInnerStyle = { ...DefaultPlotInnerStyle };\n const rect = this.props.container.getBoundingClientRect();\n\n const x = e.clientX - rect.left - shiftX;\n const y = e.clientY - rect.top - shiftY;\n plotInnerStyle.left = x;\n plotInnerStyle.top = y;\n return plotInnerStyle;\n }\n\n onDragAnchorMouseDown(e) {\n e.persist();\n const shiftX = e.clientX - e.target.getBoundingClientRect().left;\n const shiftY = e.clientY - e.target.getBoundingClientRect().top;\n this.setState({ shiftX, shiftY }, () => {\n this.setState({ plotInnerStyle: this.plotInnerStyleFromMouseEvent(e) });\n });\n this.props.onDragStart(\n this.props.messageId,\n this.props.signalSpec.uid,\n shiftX,\n shiftY\n );\n }\n\n onDragAnchorMouseUp(e) {\n this.props.onDragEnd();\n this.setState({\n plotInnerStyle: null,\n shiftX: 0,\n shiftY: 0\n });\n }\n\n onDragStart(e) {\n e.preventDefault();\n return false;\n }\n\n render() {\n const { plotInnerStyle } = this.state;\n const canReceiveDropClass = this.props.canReceiveGraphDrop\n ? 'is-droppable'\n : null;\n\n return (\n <div\n className=\"cabana-explorer-visuals-plot\"\n ref={this.props.onGraphRefAvailable}\n >\n <div\n className={cx(\n 'cabana-explorer-visuals-plot-inner',\n canReceiveDropClass\n )}\n style={plotInnerStyle || null}\n >\n <div\n className=\"cabana-explorer-visuals-plot-draganchor\"\n onMouseDown={this.onDragAnchorMouseDown}\n >\n <span className=\"fa fa-bars\" />\n </div>\n {this.props.plottedSignals.map(\n ({ messageId, signalUid, messageName }) => {\n const signal = Object.values(\n this.props.messages[messageId].frame.signals\n ).find((s) => s.uid === signalUid);\n const colors = signal.getColors(messageId);\n\n return (\n <div\n className=\"cabana-explorer-visuals-plot-header\"\n key={`${messageId}_${signal.uid}`}\n >\n <div className=\"cabana-explorer-visuals-plot-header-toggle\">\n <button\n className=\"button--tiny\"\n onClick={() => this.props.unplot(messageId, signalUid)}\n >\n <span>Hide Plot</span>\n </button>\n </div>\n <div className=\"cabana-explorer-visuals-plot-header-copy\">\n <div className=\"cabana-explorer-visuals-plot-message\">\n <span>\n {messageName}\n {' '}\n {messageId}\n </span>\n </div>\n <div className=\"cabana-explorer-visuals-plot-signal\">\n <div\n className=\"cabana-explorer-visuals-plot-signal-color\"\n style={{ background: `rgb(${colors}` }}\n />\n <strong>{signal.name}</strong>\n </div>\n </div>\n </div>\n );\n }\n )}\n <Measure bounds onResize={this.onPlotResize}>\n {({ measureRef }) => (\n <div\n ref={measureRef}\n className=\"cabana-explorer-visuals-plot-container\"\n >\n <Vega\n onNewView={this.onNewView}\n logLevel={1}\n signalListeners={{\n clickTime: this.onSignalClickTime,\n segment: this.onSignalSegment\n }}\n renderer=\"canvas\"\n spec={this.state.spec}\n actions={false}\n data={{\n table: this.state.data.series\n }}\n />\n </div>\n )}\n </Measure>\n </div>\n </div>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nimport CanGraph from './CanGraph';\n\nrequire('element-closest');\n\nexport default class CanGraphList extends Component {\n static propTypes = {\n plottedSignals: PropTypes.array.isRequired,\n messages: PropTypes.object.isRequired,\n onGraphTimeClick: PropTypes.func.isRequired,\n seekTime: PropTypes.number.isRequired,\n onSegmentChanged: PropTypes.func.isRequired,\n onSignalUnplotPressed: PropTypes.func.isRequired,\n segment: PropTypes.array.isRequired,\n mergePlots: PropTypes.func.isRequired\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n draggingSignal: {},\n dragPos: null,\n dragShift: null,\n graphToReceiveDrop: null\n };\n\n this.plotListRef = null;\n this.plotRefs = [];\n this.renderSignalPlot = this.renderSignalPlot.bind(this);\n this.onPlotListRefReady = this.onPlotListRefReady.bind(this);\n this.onGraphDragStart = this.onGraphDragStart.bind(this);\n this.onGraphDragEnd = this.onGraphDragEnd.bind(this);\n this.onMouseMove = this.onMouseMove.bind(this);\n }\n\n onGraphDragStart(messageId, signalUid, shiftX, shiftY) {\n this.setState({\n draggingSignal: { messageId, signalUid },\n dragShift: { x: shiftX, y: shiftY }\n });\n }\n\n determineDraggingGraph() {\n const { draggingSignal } = this.state;\n return this.plotRefs.find(\n ({ messageId, signalUid }) => draggingSignal.messageId === messageId\n && draggingSignal.signalUid === signalUid\n );\n }\n\n onMouseMove(e) {\n const { dragShift } = this.state;\n if (dragShift === null) {\n if (this.state.graphToReceiveDrop !== null) {\n this.setState({ graphToReceiveDrop: null });\n }\n return;\n }\n const rect = this.plotListRef.getBoundingClientRect();\n const draggingGraph = this.determineDraggingGraph();\n if (draggingGraph) {\n draggingGraph.ref.hidden = true;\n const ele = document.elementFromPoint(e.clientX, e.clientY);\n draggingGraph.ref.hidden = false;\n const closestPlot = ele.closest('.cabana-explorer-visuals-plot');\n const closestPlotRef = this.plotRefs.find(\n ({ ref, messageId, signalUid }) => !(\n messageId === draggingGraph.messageId\n && signalUid === draggingGraph.signalUid\n ) && ref.isEqualNode(closestPlot)\n );\n if (closestPlotRef) {\n this.setState({ graphToReceiveDrop: closestPlotRef });\n } else {\n this.setState({ graphToReceiveDrop: null });\n }\n }\n const left = e.clientX - rect.left - dragShift.x;\n const top = e.clientY - rect.top - dragShift.y;\n\n this.setState({ dragPos: { left, top } });\n }\n\n onGraphDragEnd() {\n if (this.state.graphToReceiveDrop !== null) {\n this.props.mergePlots({\n fromPlot: this.state.draggingSignal,\n toPlot: this.state.graphToReceiveDrop\n });\n }\n\n this.setState({\n draggingSignal: {},\n dragShift: null,\n dragPos: null,\n graphToReceiveDrop: null\n });\n }\n\n addCanGraphRef(ref, messageId, signalUid) {\n if (ref) {\n let { plotRefs } = this;\n plotRefs = plotRefs\n .filter(\n (ref) => !(ref.messageId === messageId && ref.signalUid === signalUid)\n )\n .concat([{ messageId, signalUid, ref }]);\n this.plotRefs = plotRefs;\n }\n }\n\n renderSignalPlot(plottedSignals, index) {\n const { draggingSignal, graphToReceiveDrop } = this.state;\n const { messageId, signalUid } = plottedSignals[0];\n const msg = this.props.messages[messageId];\n const signal = Object.values(msg.frame.signals).find(\n (s) => s.uid === signalUid\n );\n\n if (!this.plotListRef) {\n return [];\n }\n\n const isDragging = draggingSignal.signalUid === signalUid\n && draggingSignal.messageId === messageId;\n const canReceiveGraphDrop = graphToReceiveDrop\n && graphToReceiveDrop.signalUid === signalUid\n && graphToReceiveDrop.messageId === messageId;\n plottedSignals = plottedSignals.map((plottedSignal) => ({\n messageName: this.props.messages[plottedSignal.messageId].frame.name,\n ...plottedSignal\n }));\n const key = plottedSignals.reduce(\n (key, { messageId, signalUid }) => `${key + messageId}_${signalUid}`,\n ''\n );\n return (\n <CanGraph\n onGraphRefAvailable={(ref) => {\n this.addCanGraphRef(ref, messageId, signalUid);\n }}\n key={key}\n unplot={this.props.onSignalUnplotPressed}\n messages={this.props.messages}\n messageId={messageId}\n messageName={msg.frame ? msg.frame.name : null}\n signalSpec={Object.assign(Object.create(signal), signal)}\n onSegmentChanged={this.props.onSegmentChanged}\n segment={this.props.segment}\n onRelativeTimeClick={this.props.onGraphTimeClick}\n currentTime={this.props.seekTime}\n onDragStart={this.onGraphDragStart}\n onDragEnd={this.onGraphDragEnd}\n container={this.plotListRef}\n dragPos={isDragging ? this.state.dragPos : null}\n canReceiveGraphDrop={canReceiveGraphDrop}\n plottedSignals={plottedSignals}\n live={this.props.live}\n />\n );\n }\n\n onPlotListRefReady(ref) {\n this.plotListRef = ref;\n }\n\n render() {\n return (\n <div\n className=\"cabana-explorer-visuals-plots\"\n ref={this.onPlotListRefReady}\n onMouseMove={this.onMouseMove}\n onMouseLeave={this.onGraphDragEnd}\n onMouseUp={this.onGraphDragEnd}\n >\n {this.props.plottedSignals.map(this.renderSignalPlot)}\n </div>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport Hls from '@commaai/hls.js';\n\nexport default class HLS extends Component {\n static propTypes = {\n source: PropTypes.string.isRequired,\n startTime: PropTypes.number.isRequired,\n playbackSpeed: PropTypes.number.isRequired,\n playing: PropTypes.bool.isRequired,\n onVideoElementAvailable: PropTypes.func,\n onClick: PropTypes.func,\n onLoadStart: PropTypes.func,\n onLoadEnd: PropTypes.func,\n onPlaySeek: PropTypes.func,\n onRestart: PropTypes.func\n };\n\n componentWillReceiveProps(nextProps) {\n this.videoElement.playbackRate = nextProps.playbackSpeed;\n\n if (nextProps.source !== this.props.source) {\n this.loadSource(nextProps.source);\n }\n if (nextProps.playing) {\n if (\n this.videoElement\n && (this.videoElement.paused || this.videoElement.currentTime < 0.01)\n ) {\n this.videoElement.play();\n }\n } else {\n this.videoElement.pause();\n }\n }\n\n componentDidMount() {\n this.player = new Hls({\n enableWorker: false,\n disablePtsDtsCorrectionInMp4Remux: false,\n });\n this.player.on(Hls.Events.ERROR, (event, data) => {\n if (data.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n // try to recover network error\n console.log('fatal network error encountered, try to recover');\n this.player.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n console.log('fatal media error encountered, try to recover');\n this.player.recoverMediaError();\n break;\n default:\n // cannot recover\n this.player.destroy();\n this.player = null;\n break;\n }\n }\n });\n this.loadSource();\n }\n\n onSeeking = () => {\n if (!this.props.playing) {\n this.props.onLoadStart();\n this.props.onPlaySeek(this.videoElement.currentTime);\n }\n };\n\n // legacy outer scope variable. Revisit this to see if putting in state\n // makes more sense\n shouldInitVideoTime = true;\n\n onSeeked = () => {\n if (!this.props.playing) {\n if (this.shouldInitVideoTime) {\n this.videoElement.currentTime = this.props.startTime;\n this.shouldInitVideoTime = false;\n }\n this.props.onLoadEnd();\n }\n };\n\n loadSource(source = this.props.source) {\n if (this.videoElement) {\n this.player.loadSource(source);\n this.player.attachMedia(this.videoElement);\n this.props.onVideoElementAvailable(this.videoElement);\n }\n }\n\n componentWillUnmount() {\n // destroy hls video source\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n render() {\n return (\n <div\n className=\"cabana-explorer-visuals-camera-wrapper\"\n onClick={this.props.onClick}\n >\n <video\n ref={(video) => {\n this.videoElement = video;\n }}\n autoPlay={this.props.playing}\n muted\n onWaiting={this.props.onLoadStart}\n onPlaying={this.props.onLoadEnd}\n onSeeking={this.onSeeking}\n onSeeked={this.onSeeked}\n />\n </div>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport default class PlayButton extends Component {\n static propTypes = {\n onPlay: PropTypes.func,\n onPause: PropTypes.func,\n isPlaying: PropTypes.bool,\n className: PropTypes.string\n };\n\n constructor(props) {\n super(props);\n this.state = { hover: false };\n\n this.onClick = this.onClick.bind(this);\n }\n\n imageSource() {\n const { hover } = this.state;\n const { isPlaying } = this.props;\n if (isPlaying) {\n if (hover) {\n return `${process.env.PUBLIC_URL}/img/ic_pause_circle_filled_white_24px.svg`;\n }\n return `${process.env.PUBLIC_URL}/img/ic_pause_circle_outline_white_24px.svg`;\n }\n if (hover) {\n return `${process.env.PUBLIC_URL}/img/ic_play_circle_filled_white_24px.svg`;\n }\n return `${process.env.PUBLIC_URL}/img/ic_play_circle_outline_white_24px.svg`;\n }\n\n onClick(e) {\n const { isPlaying } = this.props;\n\n if (!isPlaying) {\n this.props.onPlay();\n } else {\n this.props.onPause();\n }\n }\n\n render() {\n return (\n <img\n src={this.imageSource()}\n alt={this.props.isPlaying ? 'Pause' : 'Play'}\n className={this.props.className}\n onClick={this.onClick}\n onMouseOver={() => this.setState({ hover: true })}\n onMouseLeave={() => this.setState({ hover: false })}\n />\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport PlayButton from '../PlayButton';\nimport debounce from '../../utils/debounce';\n\nexport default class RouteSeeker extends Component {\n static propTypes = {\n videoLength: PropTypes.number.isRequired,\n segmentIndices: PropTypes.arrayOf(PropTypes.number),\n segment: PropTypes.arrayOf(PropTypes.number),\n onUserSeek: PropTypes.func,\n onPlaySeek: PropTypes.func,\n video: PropTypes.node,\n onPause: PropTypes.func,\n onPlay: PropTypes.func,\n playing: PropTypes.bool,\n segmentProgress: PropTypes.func,\n ratioTime: PropTypes.func,\n nearestFrameTime: PropTypes.number\n };\n\n static hiddenMarkerStyle = { display: 'none', left: 0 };\n\n static zeroSeekedBarStyle = { width: 0 };\n\n static hiddenTooltipStyle = { display: 'none', left: 0 };\n\n static markerWidth = 20;\n\n static tooltipWidth = 50;\n\n constructor(props) {\n super(props);\n this.state = {\n seekedBarStyle: RouteSeeker.zeroSeekedBarStyle,\n markerStyle: RouteSeeker.hiddenMarkerStyle,\n tooltipStyle: RouteSeeker.hiddenTooltipStyle,\n ratio: 0,\n tooltipTime: '0:00',\n isPlaying: false,\n isDragging: false\n };\n\n this.onMouseMove = this.onMouseMove.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onMouseDown = this.onMouseDown.bind(this);\n this.onMouseUp = this.onMouseUp.bind(this);\n this.onClick = this.onClick.bind(this);\n this.onPlay = this.onPlay.bind(this);\n this.onPause = this.onPause.bind(this);\n this.executePlayTimer = this.executePlayTimer.bind(this);\n }\n\n componentWillReceiveProps(nextProps) {\n const { ratio } = this.state;\n\n if (\n JSON.stringify(this.props.segmentIndices)\n !== JSON.stringify(nextProps.segmentIndices)\n ) {\n this.setState({\n seekedBarStyle: RouteSeeker.zeroSeekedBarStyle,\n markerStyle: RouteSeeker.hiddenMarkerStyle,\n ratio: 0\n });\n } else if (nextProps.videoLength !== this.props.videoLength) {\n // adjust ratio in line with new videoLength\n const secondsSeeked = ratio * this.props.videoLength;\n const newRatio = secondsSeeked / nextProps.videoLength;\n this.updateSeekedBar(newRatio);\n }\n\n if (this.props.nearestFrameTime !== nextProps.nearestFrameTime) {\n const newRatio = this.props.segmentProgress(nextProps.nearestFrameTime);\n this.updateSeekedBar(newRatio);\n }\n\n if (nextProps.playing && !this.state.isPlaying) {\n this.onPlay();\n } else if (!nextProps.playing && this.state.isPlaying) {\n this.onPause();\n }\n }\n\n componentWillUnmount() {\n window.cancelAnimationFrame(this.playTimer);\n }\n\n mouseEventXOffsetPercent(e) {\n const rect = this.progressBar.getBoundingClientRect();\n const x = e.clientX - rect.left;\n\n return 100 * (x / this.progressBar.offsetWidth);\n }\n\n updateDraggingSeek = debounce((ratio) => this.props.onUserSeek(ratio), 250);\n\n onMouseMove(e) {\n const markerOffsetPct = this.mouseEventXOffsetPercent(e);\n if (markerOffsetPct < 0) {\n this.onMouseLeave();\n return;\n }\n const { markerWidth } = RouteSeeker;\n\n const markerLeft = `calc(${markerOffsetPct}% - ${markerWidth / 2}px)`;\n const markerStyle = {\n display: '',\n left: markerLeft\n };\n const { tooltipWidth } = RouteSeeker;\n const tooltipLeft = `calc(${markerOffsetPct}% - ${tooltipWidth / 2}px)`;\n\n const tooltipStyle = { display: 'flex', left: tooltipLeft };\n const ratio = Math.max(0, markerOffsetPct / 100);\n if (this.state.isDragging) {\n this.updateSeekedBar(ratio);\n this.updateDraggingSeek(ratio);\n }\n\n this.setState({\n markerStyle,\n tooltipStyle,\n tooltipTime: this.props.ratioTime(ratio).toFixed(3)\n });\n }\n\n onMouseLeave(e) {\n this.setState({\n markerStyle: RouteSeeker.hiddenMarkerStyle,\n tooltipStyle: RouteSeeker.hiddenTooltipStyle,\n isDragging: false\n });\n }\n\n updateSeekedBar(ratio) {\n const seekedBarStyle = { width: `${100 * ratio}%` };\n this.setState({ seekedBarStyle, ratio });\n }\n\n onClick(e) {\n let ratio = this.mouseEventXOffsetPercent(e) / 100;\n ratio = Math.min(1, Math.max(0, ratio));\n this.updateSeekedBar(ratio);\n this.props.onUserSeek(ratio);\n }\n\n onPlay() {\n this.playTimer = window.requestAnimationFrame(this.executePlayTimer);\n let { ratio } = this.state;\n if (ratio >= 1) {\n ratio = 0;\n }\n this.setState({ isPlaying: true, ratio });\n this.props.onPlay();\n }\n\n executePlayTimer() {\n const { videoElement } = this.props;\n if (videoElement === null) {\n this.playTimer = window.requestAnimationFrame(this.executePlayTimer);\n return;\n }\n\n let { videoLength, startTime } = this.props;\n let { currentTime, duration } = videoElement;\n\n currentTime = roundTime(currentTime);\n startTime = roundTime(startTime);\n videoLength = roundTime(videoLength);\n duration = roundTime(duration);\n\n let newRatio = (currentTime - startTime) / videoLength;\n\n if (newRatio === this.state.ratio) {\n this.playTimer = window.requestAnimationFrame(this.executePlayTimer);\n return;\n }\n\n if ((newRatio >= 1 && this.props.segment && this.props.segment.length) || newRatio < 0) {\n newRatio = 0;\n currentTime = startTime;\n this.props.onUserSeek(newRatio);\n } else if (newRatio >= 1) {\n videoElement.pause();\n this.onPause();\n }\n\n if (newRatio >= 0) {\n this.updateSeekedBar(newRatio);\n this.props.onPlaySeek(currentTime);\n }\n\n this.playTimer = window.requestAnimationFrame(this.executePlayTimer);\n }\n\n onPause() {\n window.cancelAnimationFrame(this.playTimer);\n this.setState({ isPlaying: false });\n this.props.onPause();\n }\n\n onMouseDown() {\n if (!this.state.isDragging) {\n this.setState({ isDragging: true });\n }\n }\n\n onMouseUp() {\n if (this.state.isDragging) {\n this.setState({ isDragging: false });\n }\n }\n\n render() {\n const { seekedBarStyle, markerStyle, tooltipStyle } = this.state;\n return (\n <div className=\"cabana-explorer-visuals-camera-seeker\">\n <PlayButton\n className=\"cabana-explorer-visuals-camera-seeker-playbutton\"\n onPlay={this.onPlay}\n onPause={this.onPause}\n isPlaying={this.state.isPlaying}\n />\n <div\n className=\"cabana-explorer-visuals-camera-seeker-progress\"\n onMouseMove={this.onMouseMove}\n onMouseLeave={this.onMouseLeave}\n onMouseDown={this.onMouseDown}\n onMouseUp={this.onMouseUp}\n onClick={this.onClick}\n ref={(ref) => (this.progressBar = ref)}\n >\n <div\n className=\"cabana-explorer-visuals-camera-seeker-progress-tooltip\"\n style={tooltipStyle}\n >\n {this.state.tooltipTime}\n </div>\n <div\n className=\"cabana-explorer-visuals-camera-seeker-progress-marker\"\n style={markerStyle}\n />\n <div\n className=\"cabana-explorer-visuals-camera-seeker-progress-inner\"\n style={seekedBarStyle}\n />\n </div>\n </div>\n );\n }\n}\n\nfunction roundTime(time) {\n return Math.round(time * 1000) / 1000;\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { StyleSheet, css } from 'aphrodite/no-important';\nimport { video as VideoApi } from '@commaai/comma-api';\n\nimport HLS from './HLS';\nimport RouteSeeker from './RouteSeeker/RouteSeeker';\n\nconst Styles = StyleSheet.create({\n loadingOverlay: {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 3\n },\n loadingSpinner: {\n width: '25%',\n height: '25%',\n display: 'block'\n },\n img: {\n height: 480,\n display: 'block',\n position: 'absolute',\n zIndex: 2\n },\n hls: {\n zIndex: 1,\n height: 480,\n backgroundColor: 'rgba(0,0,0,0.9)'\n },\n seekBar: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n width: '100%',\n zIndex: 4\n }\n});\n\nexport default class RouteVideoSync extends Component {\n constructor(props) {\n super(props);\n this.state = {\n shouldShowJpeg: true,\n isLoading: true,\n videoElement: null,\n source: null,\n };\n\n this.onLoadStart = this.onLoadStart.bind(this);\n this.onLoadEnd = this.onLoadEnd.bind(this);\n this.segmentProgress = this.segmentProgress.bind(this);\n this.onVideoElementAvailable = this.onVideoElementAvailable.bind(this);\n this.onUserSeek = this.onUserSeek.bind(this);\n this.onPlaySeek = this.onPlaySeek.bind(this);\n this.ratioTime = this.ratioTime.bind(this);\n }\n\n componentWillMount() {\n let videoApi = VideoApi(this.props.url, process.env.REACT_APP_VIDEO_CDN);\n videoApi.getQcameraStreamIndex().then(() => {\n this.setState({source: videoApi.getQcameraStreamIndexUrl()});\n }).catch(() => {\n this.setState({source: videoApi.getRearCameraStreamIndexUrl()});\n })\n }\n\n componentDidUpdate(prevProps) {\n const { userSeekTime } = this.props;\n const { videoElement } = this.state;\n\n if (\n prevProps.userSeekTime\n && userSeekTime !== prevProps.userSeekTime\n ) {\n if (videoElement) {\n videoElement.currentTime = userSeekTime - this.props.videoOffset;\n }\n }\n }\n\n onVideoElementAvailable(videoElement) {\n this.setState({ videoElement });\n }\n\n onUserSeek(ratio) {\n /* ratio in [0,1] */\n\n const { videoElement } = this.state;\n const { onUserSeek } = this.props;\n const seekTime = this.ratioTime(ratio);\n const funcSeekToRatio = () => onUserSeek(seekTime);\n\n if (Number.isNaN(videoElement.duration)) {\n return;\n }\n videoElement.currentTime = seekTime - this.props.videoOffset;\n\n if (ratio !== 0) {\n funcSeekToRatio();\n }\n }\n\n onPlaySeek(offset) {\n this.seekTime = offset + this.props.videoOffset;\n this.props.onPlaySeek(this.seekTime);\n }\n\n onLoadStart() {\n this.setState({\n shouldShowJpeg: true,\n isLoading: true\n });\n }\n\n onLoadEnd() {\n this.setState({\n shouldShowJpeg: false,\n isLoading: false\n });\n }\n\n loadingOverlay() {\n return (\n <div className={css(Styles.loadingOverlay)}>\n <img\n className={css(Styles.loadingSpinner)}\n src={`${process.env.PUBLIC_URL}/img/loading.svg`}\n alt=\"Loading video\"\n />\n </div>\n );\n }\n\n videoLength() {\n if (this.props.segment.length) {\n return this.props.segment[1] - this.props.segment[0];\n }\n\n if (this.state.videoElement) {\n return this.state.videoElement.duration;\n }\n\n return 0;\n }\n\n startTime() {\n if (this.props.segment.length) {\n return this.props.segment[0];\n }\n\n return 0;\n }\n\n segmentProgress(currentTime) {\n // returns progress as number in [0,1]\n const startTime = this.startTime();\n\n if (currentTime < startTime) {\n currentTime = startTime;\n }\n\n const ratio = (currentTime - startTime) / this.videoLength();\n return Math.max(0, Math.min(1, ratio));\n }\n\n ratioTime(ratio) {\n return ratio * this.videoLength() + this.startTime();\n }\n\n nearestFrameUrl() {\n const { thumbnails } = this.props;\n if (!this.seekTime) {\n return '';\n }\n for (let i = 0, l = thumbnails.length; i < l; ++i) {\n if (Math.abs(thumbnails[i].monoTime - this.seekTime) < 5) {\n const data = btoa(String.fromCharCode(...thumbnails[i].data));\n return `data:image/jpeg;base64,${data}`;\n }\n }\n return '';\n }\n\n render() {\n const {\n isLoading,\n shouldShowJpeg,\n videoElement,\n } = this.state;\n const {\n userSeekTime,\n url,\n playSpeed,\n playing,\n onVideoClick,\n segmentIndices,\n startTime,\n segment\n } = this.props;\n\n return (\n <div className=\"cabana-explorer-visuals-camera\">\n {isLoading ? this.loadingOverlay() : null}\n {shouldShowJpeg ? (\n <img\n src={this.nearestFrameUrl()}\n className={css(Styles.img)}\n alt={`Camera preview at t = ${Math.round(userSeekTime)}`}\n />\n ) : null}\n {this.state.source && <HLS\n className={css(Styles.hls)}\n source={this.state.source}\n startTime={(startTime || 0) - this.props.videoOffset}\n videoLength={this.videoLength()}\n playbackSpeed={playSpeed}\n onVideoElementAvailable={this.onVideoElementAvailable}\n playing={playing}\n onClick={onVideoClick}\n onLoadStart={this.onLoadStart}\n onLoadEnd={this.onLoadEnd}\n onUserSeek={this.onUserSeek}\n onPlaySeek={this.onPlaySeek}\n />}\n <RouteSeeker\n className={css(Styles.seekBar)}\n nearestFrameTime={userSeekTime}\n segmentProgress={this.segmentProgress}\n startTime={this.startTime() - this.props.videoOffset}\n videoLength={this.videoLength()}\n segmentIndices={segmentIndices}\n onUserSeek={this.onUserSeek}\n onPlaySeek={this.onPlaySeek}\n videoElement={videoElement}\n onPlay={this.props.onPlay}\n onPause={this.props.onPause}\n playing={this.props.playing}\n ratioTime={this.ratioTime}\n segment={segment}\n />\n </div>\n );\n }\n}\n\nRouteVideoSync.propTypes = {\n segment: PropTypes.array.isRequired,\n thumbnails: PropTypes.array,\n url: PropTypes.string.isRequired,\n playing: PropTypes.bool.isRequired,\n onPlaySeek: PropTypes.func.isRequired,\n onUserSeek: PropTypes.func.isRequired,\n onPlay: PropTypes.func.isRequired,\n onPause: PropTypes.func.isRequired,\n userSeekTime: PropTypes.number.isRequired,\n playSpeed: PropTypes.number.isRequired,\n onVideoClick: PropTypes.func,\n segmentIndices: PropTypes.array,\n startTime: PropTypes.number\n};\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport ReactList from 'react-list';\n\nimport cx from 'classnames';\n\nexport default class CanLog extends Component {\n static ITEMS_PER_PAGE = 50;\n\n static propTypes = {\n plottedSignals: PropTypes.array,\n segmentIndices: PropTypes.array,\n onSignalUnplotPressed: PropTypes.func,\n onSignalPlotPressed: PropTypes.func,\n message: PropTypes.object,\n messageIndex: PropTypes.number,\n onMessageExpanded: PropTypes.func\n };\n\n constructor(props) {\n super(props);\n // only want to display up to length elements at a time\n // offset, length\n\n this.state = {\n length: 0,\n expandedMessages: [],\n messageHeights: [],\n allPacketsExpanded: false\n };\n\n this.renderLogListItemMessage = this.renderLogListItemMessage.bind(this);\n this.addDisplayedMessages = this.addDisplayedMessages.bind(this);\n this.renderLogListItem = this.renderLogListItem.bind(this);\n this.renderLogList = this.renderLogList.bind(this);\n this.onExpandAllChanged = this.onExpandAllChanged.bind(this);\n this.toggleExpandAllPackets = this.toggleExpandAllPackets.bind(this);\n this.toggleSignalPlot = this.toggleSignalPlot.bind(this);\n }\n\n componentWillReceiveProps(nextProps) {\n if (nextProps.message && !this.props.message) {\n this.addDisplayedMessages();\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const curMessageLength = this.props.message\n ? this.props.message.entries.length\n : 0;\n const nextMessageLength = nextProps.message\n ? nextProps.message.entries.length\n : 0;\n\n const shouldUpdate = this.props.message !== nextProps.message\n || nextMessageLength !== curMessageLength\n || nextProps.messageIndex !== this.props.messageIndex\n || nextProps.plottedSignals.length !== this.props.plottedSignals.length\n || JSON.stringify(nextProps.segmentIndices)\n !== JSON.stringify(this.props.segmentIndices)\n || JSON.stringify(nextState) !== JSON.stringify(this.state)\n || this.props.message !== nextProps.message\n || (this.props.message !== undefined\n && nextProps.message !== undefined\n && this.props.message.frame !== undefined\n && nextProps.message.frame !== undefined\n && JSON.stringify(this.props.message.frame)\n !== JSON.stringify(nextProps.message.frame));\n\n return shouldUpdate;\n }\n\n addDisplayedMessages() {\n const { length } = this.state;\n const newLength = length + CanLog.ITEMS_PER_PAGE;\n\n this.setState({ length: newLength });\n }\n\n expandMessage(msg, msgIdx) {\n this.setState({\n expandedMessages: this.state.expandedMessages.concat([msg.time])\n });\n this.props.onMessageExpanded();\n }\n\n collapseMessage(msg, msgIdx) {\n this.setState({\n expandedMessages: this.state.expandedMessages.filter(\n (expMsgTime) => expMsgTime !== msg.time\n )\n });\n }\n\n isSignalPlotted(msgId, signalUid) {\n const plottedSignal = this.props.plottedSignals.find((plot) => plot.some(\n (signal) => signal.messageId === msgId && signal.signalUid === signalUid\n ));\n return plottedSignal !== undefined;\n }\n\n signalValuePretty(signal, value) {\n if (signal.isFloat) {\n return value.toFixed(3);\n }\n return value;\n }\n\n isMessageExpanded(msg) {\n return this.state.expandedMessages.indexOf(msg.time) !== -1;\n }\n\n toggleSignalPlot(msg, signalUid, plotted) {\n if (!plotted) {\n this.props.onSignalPlotPressed(msg, signalUid);\n } else {\n this.props.onSignalUnplotPressed(msg, signalUid);\n }\n }\n\n toggleExpandPacketSignals(msgEntry) {\n if (!this.props.message.frame) {\n return;\n }\n const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);\n\n const msgHasSignals = Object.keys(this.props.message.frame.signals).length > 0;\n if (msgIsExpanded && msgHasSignals) {\n this.setState({\n expandedMessages: this.state.expandedMessages.filter(\n (expMsgTime) => expMsgTime !== msgEntry.time\n )\n });\n } else if (msgHasSignals) {\n this.setState({\n expandedMessages: this.state.expandedMessages.concat([msgEntry.time])\n });\n this.props.onMessageExpanded();\n } else {\n }\n }\n\n renderLogListItemSignals(msgEntry) {\n const { message } = this.props;\n return (\n <div className=\"signals-log-list-signals\">\n {Object.entries(msgEntry.signals).map(([name, value]) => {\n const signal = message.frame.signals[name];\n if (signal === undefined) {\n // Signal removed?\n return null;\n }\n const unit = signal.unit.length > 0 ? signal.unit : 'units';\n const isPlotted = this.isSignalPlotted(message.id, signal.uid);\n const plottedButtonClass = isPlotted ? null : 'button--alpha';\n const plottedButtonText = isPlotted ? 'Hide Plot' : 'Show Plot';\n return (\n <div key={name} className=\"signals-log-list-signal\">\n <div className=\"signals-log-list-signal-message\">\n <span>{name}</span>\n </div>\n <div className=\"signals-log-list-signal-value\">\n <span>\n (\n <strong>{this.signalValuePretty(signal, value)}</strong>\n {' '}\n {unit}\n)\n </span>\n </div>\n <div\n className=\"signals-log-list-signal-action\"\n onClick={() => {\n this.toggleSignalPlot(message.id, signal.uid, isPlotted);\n }}\n >\n <button className={cx('button--tiny', plottedButtonClass)}>\n <span>{plottedButtonText}</span>\n </button>\n </div>\n </div>\n );\n })}\n </div>\n );\n }\n\n renderLogListItemMessage(msgEntry, key) {\n const { message } = this.props;\n const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);\n const msgHasSignals = Object.keys(msgEntry.signals).length > 0;\n const hasSignalsClass = msgHasSignals ? 'has-signals' : null;\n const expandedClass = msgIsExpanded ? 'is-expanded' : null;\n const row = (\n <div\n key={key}\n className={cx('signals-log-list-item', hasSignalsClass, expandedClass)}\n >\n <div\n className=\"signals-log-list-item-header\"\n onClick={() => {\n this.toggleExpandPacketSignals(msgEntry);\n }}\n >\n <div className=\"signals-log-list-message\">\n <strong>\n {(message.frame ? message.frame.name : null) || message.id}\n </strong>\n </div>\n <div className=\"signals-log-list-time\">\n <span>\n[\n {msgEntry.relTime.toFixed(3)}\n]\n </span>\n </div>\n <div className=\"signals-log-list-bytes\">\n <span className=\"t-mono\">{msgEntry.hexData}</span>\n </div>\n </div>\n <div className=\"signals-log-list-item-body\">\n {msgIsExpanded ? this.renderLogListItemSignals(msgEntry) : null}\n </div>\n </div>\n );\n\n return row;\n }\n\n renderLogListItem(index, key) {\n let offset = this.props.messageIndex;\n if (offset === 0 && this.props.segmentIndices.length === 2) {\n offset = this.props.segmentIndices[0];\n }\n if (offset + index < 0) {\n debugger;\n }\n if (offset + index < this.props.message.entries.length) {\n return this.renderLogListItemMessage(\n this.props.message.entries[offset + index],\n key\n );\n }\n return null;\n }\n\n renderLogList(items, ref) {\n return (\n <div className=\"signals-log-list\">\n <div className=\"signals-log-list-header\">\n <div className=\"signals-log-list-message\">Message</div>\n <div className=\"signals-log-list-time\">Time</div>\n <div className=\"signals-log-list-bytes\">Bytes</div>\n </div>\n <div className=\"signals-log-list-items\" ref={ref}>\n {items}\n </div>\n </div>\n );\n }\n\n listLength() {\n const { segmentIndices, messageIndex } = this.props;\n if (messageIndex > 0) {\n return this.props.message.entries.length - messageIndex;\n }\n if (segmentIndices.length === 2) {\n return segmentIndices[1] - segmentIndices[0];\n }\n if (this.props.message) {\n return this.props.message.entries.length;\n }\n // no message yet\n return 0;\n }\n\n onExpandAllChanged(e) {\n this.setState({ allPacketsExpanded: e.target.checked });\n }\n\n toggleExpandAllPackets() {\n this.setState({ allPacketsExpanded: !this.state.allPacketsExpanded });\n }\n\n render() {\n const expandAllText = this.state.allPacketsExpanded\n ? 'Collapse All'\n : 'Expand All';\n const expandAllClass = this.state.allPacketsExpanded\n ? null\n : 'button--alpha';\n return (\n <div className=\"cabana-explorer-signals-log\">\n <div className=\"cabana-explorer-signals-log-header\">\n <strong>Message Packets</strong>\n <button\n className={cx('button--tiny', expandAllClass)}\n onClick={this.toggleExpandAllPackets}\n >\n {expandAllText}\n </button>\n </div>\n <div className=\"cabana-explorer-signals-log-body\">\n <ReactList\n itemRenderer={this.renderLogListItem}\n itemsRenderer={this.renderLogList}\n length={this.listLength()}\n pageSize={50}\n updateWhenThisValueChanges={this.props.messageIndex}\n type=\"variable\"\n />\n </div>\n </div>\n );\n }\n}\n","function findTimeIndex(entries, time) {\n return entries.findIndex((e) => e.time >= time);\n}\n\nfunction findRelativeTimeIndex(entries, relTime) {\n return entries.findIndex((e) => e.relTime >= relTime);\n}\n\nfunction findSegmentIndices(\n entries,\n [segmentTimeLow, segmentTimeHi],\n isRelative\n) {\n /*\n Finds pair of indices (inclusive, exclusive) within entries array\n whose timestamps match segmentTimeLow and segmentTimeHi.\n if isRelative === true, then the segment times\n are assumed to correspond to the `relTime` field of each entry.\n\n Returns `[segmentIdxLow, segmentIdxHigh]`\n (inclusive, exclusive)\n */\n const timeIndexFunc = isRelative === true ? findRelativeTimeIndex : findTimeIndex;\n\n const segmentIdxLow = Math.max(0, timeIndexFunc(entries, segmentTimeLow));\n\n const upperSegments = entries.slice(segmentIdxLow);\n const upperSegmentIdxHi = timeIndexFunc(upperSegments, segmentTimeHi);\n const segmentIdxHi = upperSegmentIdxHi >= 0\n ? upperSegmentIdxHi + segmentIdxLow + 1\n : entries.length - 1;\n\n return [\n segmentIdxLow,\n Math.max(0, Math.min(segmentIdxHi, entries.length - 1))\n ];\n}\n\nexport default { findTimeIndex, findRelativeTimeIndex, findSegmentIndices };\n","import React, { Component } from 'react';\n\nexport default class PlaySpeedSelector extends Component {\n constructor(props) {\n super(props);\n this.onChange = this.onChange.bind(this);\n }\n\n onChange(value) {\n if (this.props.onPlaySpeedChanged) {\n this.props.onPlaySpeedChanged(Number(value.currentTarget.value));\n }\n }\n\n render() {\n return (\n <div\n style={{\n display: 'inline-block',\n float: 'right',\n margin: 10\n }}\n >\n <label>Play speed:&nbsp;</label>\n <select\n id=\"playSpeed\"\n style={{\n width: 70\n }}\n onChange={this.onChange}\n value={this.props.playSpeed}\n >\n <option value=\"0.1\">0.1x</option>\n <option value=\"0.5\">0.5x</option>\n <option value=\"1\">1x</option>\n <option value=\"2\">2x</option>\n </select>\n </div>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nimport cx from 'classnames';\n\nimport AddSignals from './AddSignals';\nimport CanGraphList from './CanGraphList';\nimport RouteVideoSync from './RouteVideoSync';\nimport CanLog from './CanLog';\nimport Entries from '../models/can/entries';\nimport debounce from '../utils/debounce';\nimport PlaySpeedSelector from './PlaySpeedSelector';\n\nfunction clipSegment(_segment, _segmentIndices, nextMessage) {\n let segment = _segment;\n let segmentIndices = _segmentIndices;\n if (segment.length === 2) {\n const segmentStartIdx = nextMessage.entries.findIndex(\n (e) => e.relTime >= segment[0]\n );\n let segmentEndIdx = nextMessage.entries.findIndex(\n (e) => e.relTime >= segment[1]\n );\n if (segmentStartIdx !== -1) {\n if (segmentEndIdx === -1) {\n // previous segment end is past bounds of this message\n segmentEndIdx = nextMessage.entries.length - 1;\n }\n const segmentStartTime = nextMessage.entries[segmentStartIdx].relTime;\n const segmentEndTime = nextMessage.entries[segmentEndIdx].relTime;\n\n segment = [segmentStartTime, segmentEndTime];\n segmentIndices = [segmentStartIdx, segmentEndIdx];\n } else {\n // segment times are out of boudns for this message\n segment = [];\n segmentIndices = [];\n }\n }\n\n return { segment, segmentIndices };\n}\n\nexport default class Explorer extends Component {\n updateSegment = debounce((messageId, _segment) => {\n let segment = _segment;\n const { messages, selectedMessage, currentParts } = this.props;\n const { entries } = messages[selectedMessage];\n let segmentIndices = Entries.findSegmentIndices(entries, segment, true);\n\n // console.log(this.state.segment, '->', segment, segmentIndices);\n if (\n segment[0] === currentParts[0] * 60\n && segment[1] === (currentParts[1] + 1) * 60\n ) {\n segment = [];\n segmentIndices = [];\n }\n let { userSeekTime } = this.state;\n if (segment.length) {\n userSeekTime = Math.max(segment[0], userSeekTime);\n userSeekTime = Math.min(segment[1], userSeekTime);\n } else {\n userSeekTime = Math.max(currentParts[0] * 60, userSeekTime);\n userSeekTime = Math.min(currentParts[1] * 60, userSeekTime);\n }\n this.setState({\n segment,\n segmentIndices,\n userSeekIndex: segmentIndices[0],\n userSeekTime\n });\n }, 250);\n\n constructor(props) {\n super(props);\n\n this.state = {\n plottedSignals: [],\n segment: props.startSegments || [],\n segmentIndices: [],\n shouldShowAddSignal: true,\n userSeekIndex: 0,\n userSeekTime: 0,\n playing: props.autoplay,\n playSpeed: 1\n };\n\n this.onSignalPlotPressed = this.onSignalPlotPressed.bind(this);\n this.onSignalUnplotPressed = this.onSignalUnplotPressed.bind(this);\n this.onSegmentChanged = this.onSegmentChanged.bind(this);\n this.showAddSignal = this.showAddSignal.bind(this);\n this.onGraphTimeClick = this.onGraphTimeClick.bind(this);\n this.onUserSeek = this.onUserSeek.bind(this);\n this.onPlaySeek = this.onPlaySeek.bind(this);\n this.onPlay = this.onPlay.bind(this);\n this.onPause = this.onPause.bind(this);\n this.onVideoClick = this.onVideoClick.bind(this);\n this.onSignalPlotChange = this.onSignalPlotChange.bind(this);\n this.onKeyDown = this.onKeyDown.bind(this);\n this.mergePlots = this.mergePlots.bind(this);\n this.toggleShouldShowAddSignal = this.toggleShouldShowAddSignal.bind(this);\n this.changePlaySpeed = this.changePlaySpeed.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.onKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.onKeyDown);\n }\n\n onKeyDown(e) {\n if (e.keyCode === 27) {\n // escape\n this.resetSegment();\n }\n }\n\n componentWillReceiveProps(nextProps) {\n const nextMessage = nextProps.messages[nextProps.selectedMessage];\n const curMessage = this.props.messages[this.props.selectedMessage];\n let { plottedSignals } = this.state;\n\n if (Object.keys(nextProps.messages).length === 0 && Object.keys(this.props.messages).length !== 0) {\n this.resetSegment();\n }\n if (nextMessage && nextMessage.frame && nextMessage !== curMessage) {\n const nextSignalNames = Object.keys(nextMessage.frame.signals);\n\n if (nextSignalNames.length === 0) {\n this.setState({ shouldShowAddSignal: true });\n }\n }\n\n // remove plottedSignals that no longer exist\n plottedSignals = plottedSignals\n .map((plot) => plot.filter(({ messageId, signalUid }, index) => {\n const messageExists = !!nextProps.messages[messageId];\n let signalExists = true;\n if (messageExists) {\n signalExists = Object.values(\n nextProps.messages[messageId].frame.signals\n ).some((signal) => signal.uid === signalUid);\n }\n\n return messageExists && signalExists;\n }))\n .filter((plot) => plot.length > 0);\n\n this.setState({ plottedSignals });\n\n if (\n nextProps.selectedMessage\n && nextProps.selectedMessage !== this.props.selectedMessage\n ) {\n // Update segment and seek state\n // by finding a entry indices\n // corresponding to old message segment/seek times.\n\n const { segment, segmentIndices } = clipSegment(\n this.state.segment,\n this.state.segmentIndices,\n nextMessage\n );\n\n const nextSeekMsgEntry = nextMessage.entries[nextProps.seekIndex];\n let nextSeekTime;\n if (nextSeekMsgEntry) {\n nextSeekTime = nextSeekMsgEntry.relTime;\n } else if (segment.length === 2) {\n nextSeekTime = segment[0];\n } else {\n nextSeekTime = nextMessage.entries[0];\n }\n // console.log('componentWillReceiveProps', this.state.userSeekTime, '->', nextSeekTime);\n this.setState({\n segment,\n segmentIndices,\n userSeekIndex: nextProps.seekIndex,\n // userSeekTime: nextSeekTime\n });\n }\n\n if (\n nextMessage\n && curMessage\n && nextMessage.entries.length !== curMessage.entries.length\n ) {\n const { segment, segmentIndices } = clipSegment(\n this.state.segment,\n this.state.segmentIndices,\n nextMessage\n );\n // console.log(this.state.segment, '->', segment, segmentIndices);\n this.setState({ segment, segmentIndices });\n }\n }\n\n changePlaySpeed(value) {\n this.setState({\n playSpeed: value\n });\n }\n\n timeWindow() {\n const { routeStartTime, currentParts } = this.props;\n\n if (routeStartTime) {\n const partStartOffset = currentParts[0] * 60;\n const partEndOffset = (currentParts[1] + 1) * 60;\n\n const windowStartTime = routeStartTime\n .clone()\n .add(partStartOffset, 's')\n .format('HH:mm:ss');\n const windowEndTime = routeStartTime\n .clone()\n .add(partEndOffset, 's')\n .format('HH:mm:ss');\n\n return `${windowStartTime} - ${windowEndTime}`;\n }\n return '';\n }\n\n onSignalPlotPressed(messageId, signalUid) {\n let { plottedSignals } = this.state;\n\n plottedSignals = [[{ messageId, signalUid }], ...plottedSignals];\n\n this.setState({ plottedSignals });\n }\n\n onSignalUnplotPressed(messageId, signalUid) {\n const { plottedSignals } = this.state;\n const newPlottedSignals = plottedSignals\n .map((plot) => plot.filter(\n (signal) => !(signal.messageId === messageId && signal.signalUid === signalUid)\n ))\n .filter((plot) => plot.length > 0);\n\n this.setState({ plottedSignals: newPlottedSignals });\n }\n\n onSegmentChanged(messageId, segment) {\n if (Array.isArray(segment)) {\n this.updateSegment(messageId, segment);\n }\n }\n\n resetSegment() {\n const { segment, segmentIndices } = this.state;\n if (segment.length > 0 || segmentIndices.length > 0) {\n // console.log(this.state.segment, '->', segment, segmentIndices);\n this.setState({\n segment: [],\n segmentIndices: [],\n userSeekIndex: 0\n });\n }\n }\n\n showAddSignal() {\n this.setState({ shouldShowAddSignal: true });\n }\n\n toggleShouldShowAddSignal() {\n this.setState({ shouldShowAddSignal: !this.state.shouldShowAddSignal });\n }\n\n indexFromSeekTime(time) {\n // returns index guaranteed to be in [0, entries.length - 1]\n\n const { entries } = this.props.messages[this.props.selectedMessage];\n if (entries.length === 0) return null;\n\n const { segmentIndices } = this.state;\n if (segmentIndices.length === 2 && segmentIndices[0] >= 0) {\n for (\n let i = segmentIndices[0],\n l = Math.min(entries.length - 1, segmentIndices[1]);\n i <= l;\n i++\n ) {\n if (entries[i].relTime >= time) {\n return i;\n }\n }\n return segmentIndices[1];\n }\n for (let i = 0; i < entries.length; i++) {\n if (entries[i].relTime >= time) {\n return i;\n }\n }\n return entries.length - 1;\n }\n\n onUserSeek(time) {\n this.props.onUserSeek(time);\n this.setState({ userSeekTime: time });\n }\n\n onPlaySeek(time) {\n const message = this.props.messages[this.props.selectedMessage];\n if (!message || message.entries.length === 0) {\n this.props.onSeek(0, time);\n return;\n }\n\n const seekIndex = this.indexFromSeekTime(time);\n const seekTime = time;\n this.props.onSeek(seekIndex, seekTime);\n }\n\n onGraphTimeClick(messageId, time) {\n this.onUserSeek(time);\n }\n\n onPlay() {\n this.setState({ playing: true });\n }\n\n onPause() {\n this.setState({ playing: false });\n }\n\n secondsLoadedRouteRelative(currentParts) {\n return (currentParts[1] - currentParts[0] + 1) * 60;\n }\n\n secondsLoaded() {\n return this.props.partsCount * 60;\n }\n\n onVideoClick() {\n const playing = !this.state.playing;\n this.setState({ playing });\n }\n\n seekTime() {\n const { userSeekIndex } = this.state;\n const msg = this.props.messages[this.props.selectedMessage];\n return msg.entries[userSeekIndex].time;\n }\n\n onSignalPlotChange(shouldPlot, messageId, signalUid) {\n if (shouldPlot) {\n this.onSignalPlotPressed(messageId, signalUid);\n } else {\n this.onSignalUnplotPressed(messageId, signalUid);\n }\n }\n\n renderSelectMessagePrompt() {\n return (\n <div className=\"cabana-explorer-select-prompt\">\n <h1>Select a message</h1>\n </div>\n );\n }\n\n selectedMessagePlottedSignalUids() {\n const { plottedSignals } = this.state;\n return plottedSignals\n .map((plot) => plot\n .filter(\n ({ messageId, signalUid }) => messageId === this.props.selectedMessage\n )\n .map(({ signalUid }) => signalUid))\n .reduce((arr, signalUid) => arr.concat(signalUid), []);\n }\n\n renderExplorerSignals() {\n const selectedMessageKey = this.props.selectedMessage;\n const selectedMessage = this.props.messages[selectedMessageKey];\n const selectedMessageName = selectedMessage.frame !== undefined\n ? selectedMessage.frame.name\n : 'undefined';\n return (\n <div className=\"cabana-explorer-signals-wrapper\">\n <div className=\"cabana-explorer-signals-header\">\n <div className=\"cabana-explorer-signals-header-context\">\n <h5 className=\"t-capline\">Selected Message:</h5>\n <h3>{selectedMessageName}</h3>\n </div>\n <div className=\"cabana-explorer-signals-header-action\">\n <button\n className=\"button--small\"\n onClick={() => this.props.showEditMessageModal(selectedMessageKey)}\n >\n Edit\n </button>\n </div>\n </div>\n <div\n className=\"cabana-explorer-signals-subheader\"\n onClick={this.toggleShouldShowAddSignal}\n >\n <strong>Edit Signals</strong>\n </div>\n <div className=\"cabana-explorer-signals-window\">\n {this.state.shouldShowAddSignal ? (\n <AddSignals\n onConfirmedSignalChange={this.props.onConfirmedSignalChange}\n message={this.props.messages[this.props.selectedMessage]}\n onClose={() => {\n this.setState({ shouldShowAddSignal: false });\n }}\n messageIndex={this.props.seekIndex}\n onSignalPlotChange={this.onSignalPlotChange}\n plottedSignalUids={this.selectedMessagePlottedSignalUids()}\n selectedMessageKey={selectedMessageKey}\n />\n ) : null}\n <CanLog\n message={this.props.messages[this.props.selectedMessage]}\n messageIndex={this.props.seekIndex}\n segmentIndices={this.state.segmentIndices}\n plottedSignals={this.state.plottedSignals}\n onSignalPlotPressed={this.onSignalPlotPressed}\n onSignalUnplotPressed={this.onSignalUnplotPressed}\n showAddSignal={this.showAddSignal}\n onMessageExpanded={this.onPause}\n />\n </div>\n </div>\n );\n }\n\n mergePlots({ fromPlot, toPlot }) {\n const { plottedSignals } = this.state;\n\n // remove fromPlot from plottedSignals\n const fromPlotIdx = plottedSignals.findIndex((plot) => plot.some(\n (signal) => signal.signalUid === fromPlot.signalUid\n && signal.messageId === fromPlot.messageId\n ));\n plottedSignals.splice(fromPlotIdx, 1);\n\n const toPlotIdx = plottedSignals.findIndex((plot) => plot.some(\n (signal) => signal.signalUid === toPlot.signalUid\n && signal.messageId === toPlot.messageId\n ));\n plottedSignals[toPlotIdx] = [fromPlot, toPlot];\n\n this.setState({ plottedSignals });\n }\n\n render() {\n const signalsExpandedClass = this.state.shouldShowAddSignal\n ? 'is-expanded'\n : null;\n\n const { thumbnails, messages, startTime } = this.props;\n\n let graphSegment = this.state.segment;\n if (!graphSegment.length && this.props.currentParts) {\n graphSegment = [\n this.props.currentParts[0] * 60,\n (this.props.currentParts[1] + 1) * 60\n ];\n }\n return (\n <div className=\"cabana-explorer\">\n <div className={cx('cabana-explorer-signals', signalsExpandedClass)}>\n {messages[this.props.selectedMessage]\n ? this.renderExplorerSignals()\n : this.renderSelectMessagePrompt()}\n </div>\n <div className=\"cabana-explorer-visuals\">\n {this.props.live === false ? (\n <div>\n <div className=\"cabana-explorer-visuals-header g-row\">\n <PlaySpeedSelector\n playSpeed={this.state.playSpeed}\n onPlaySpeedChanged={this.changePlaySpeed}\n />\n </div>\n <RouteVideoSync\n message={messages[this.props.selectedMessage]}\n segment={this.state.segment}\n startTime={startTime}\n seekIndex={this.props.seekIndex}\n userSeekIndex={this.state.userSeekIndex}\n playing={this.state.playing}\n url={this.props.url}\n firstCanTime={this.props.firstCanTime}\n videoOffset={this.props.videoOffset}\n onVideoClick={this.onVideoClick}\n onPlaySeek={this.onPlaySeek}\n onUserSeek={this.onUserSeek}\n onPlay={this.onPlay}\n onPause={this.onPause}\n userSeekTime={this.state.userSeekTime}\n playSpeed={this.state.playSpeed}\n thumbnails={thumbnails}\n />\n </div>\n ) : null}\n {this.state.segment.length > 0 ? (\n <div\n className=\"cabana-explorer-visuals-segmentreset\"\n onClick={() => {\n this.resetSegment();\n }}\n >\n <p>Reset Segment</p>\n </div>\n ) : null}\n <CanGraphList\n plottedSignals={this.state.plottedSignals}\n messages={messages}\n onGraphTimeClick={this.onGraphTimeClick}\n seekTime={this.props.seekTime}\n onSegmentChanged={this.onSegmentChanged}\n onSignalUnplotPressed={this.onSignalUnplotPressed}\n segment={graphSegment}\n mergePlots={this.mergePlots}\n live={this.props.live}\n />\n </div>\n </div>\n );\n }\n}\n\nExplorer.propTypes = {\n selectedMessage: PropTypes.string,\n url: PropTypes.string,\n live: PropTypes.bool.isRequired,\n messages: PropTypes.objectOf(PropTypes.object),\n thumbnails: PropTypes.array.isRequired,\n onConfirmedSignalChange: PropTypes.func.isRequired,\n canFrameOffset: PropTypes.number,\n firstCanTime: PropTypes.number,\n onSeek: PropTypes.func.isRequired,\n autoplay: PropTypes.bool.isRequired,\n currentParts: PropTypes.array.isRequired,\n partsCount: PropTypes.number,\n startTime: PropTypes.number,\n startSegments: PropTypes.array\n};\n","import DbcUtils from '../../utils/dbc';\n\nconst unsignedTransformation = (field) => (value, signal) => {\n if (value !== '') {\n value = Number(value) || 0;\n\n if (value < 0) {\n value = 0;\n }\n }\n signal[field] = value;\n return signal;\n};\n\nexport default [\n {\n field: 'name',\n title: 'Name',\n type: 'string'\n },\n {\n field: 'size',\n title: 'Size',\n type: 'number',\n transform: unsignedTransformation('size')\n },\n {\n field: 'startBit',\n title: (signal) => (signal.isLittleEndian ? 'Least significant bit' : 'Most significant bit'),\n type: 'number',\n transform: unsignedTransformation('startBit')\n },\n {\n field: 'isLittleEndian',\n title: 'Endianness',\n type: 'option',\n options: {\n options: ['Little', 'Big'],\n optionValues: { Little: true, Big: false }\n },\n transform: (isLittleEndian, signal) => {\n if (signal.isLittleEndian !== isLittleEndian) {\n const { startBit } = signal;\n\n if (isLittleEndian) {\n // big endian -> little endian\n const startByte = Math.floor(signal.startBit / 8);\n const endByte = Math.floor((signal.startBit - signal.size + 1) / 8);\n\n if (startByte === endByte) {\n signal.startBit = signal.startBit - signal.size + 1;\n } else {\n signal.startBit = DbcUtils.matrixBitNumber(startBit);\n }\n } else {\n // little endian -> big endian\n const startByte = Math.floor(signal.startBit / 8);\n const endByte = Math.floor((signal.startBit + signal.size - 1) / 8);\n\n if (startByte === endByte) {\n signal.startBit = signal.startBit + signal.size - 1;\n } else {\n signal.startBit = DbcUtils.bigEndianBitIndex(startBit);\n }\n }\n signal.isLittleEndian = isLittleEndian;\n }\n return signal;\n }\n },\n {\n field: 'isSigned',\n title: 'Sign',\n type: 'option',\n options: {\n options: ['Signed', 'Unsigned'],\n optionValues: { Signed: true, Unsigned: false }\n }\n },\n {\n field: 'factor',\n title: 'Factor',\n type: 'number'\n },\n {\n field: 'offset',\n title: 'Offset',\n type: 'number'\n },\n {\n field: 'unit',\n title: 'Unit',\n type: 'string'\n },\n {\n field: 'comment',\n title: 'Comment',\n type: 'string'\n },\n {\n field: 'min',\n title: 'Minimum value',\n type: 'number'\n },\n {\n field: 'max',\n title: 'Maximum value',\n type: 'number'\n }\n];\n","import React, { Component } from 'react';\n\nexport default class Field extends Component {\n render() {\n const { title, htmlFor, children } = this.props;\n return (\n <div className=\"form-field form-field--small\">\n <label htmlFor={htmlFor}>{title}</label>\n {children}\n </div>\n );\n }\n}\n","import React from 'react';\n\nimport FIELDS from './FIELDS';\nimport NumberField from './NumberField';\nimport StringField from './StringField';\nimport OptionField from './OptionField';\n\nconst FieldMap = {\n number: NumberField,\n option: OptionField,\n string: StringField\n};\n\nexport default ({\n signal,\n onSignalRemove,\n isExpanded,\n getSignalEdited,\n update\n}) => (\n <div className=\"signals-legend-entry-form\">\n {FIELDS.map((field) => {\n const Node = FieldMap[field.type];\n return (\n <div className=\"signals-legend-entry-form-field\" key={field.field}>\n <Node\n fieldSpec={field}\n signal={signal}\n isExpanded={isExpanded}\n signalEdited={getSignalEdited(field.field)}\n updateField={update}\n />\n </div>\n );\n })}\n <div className=\"signals-legend-entry-form-remove\">\n <button\n className=\"button--tiny button--alpha\"\n onClick={() => onSignalRemove(signal)}\n >\n Remove Signal\n </button>\n </div>\n </div>\n);\n","import React from 'react';\nimport Field from './Field';\n\nexport default ({\n fieldSpec,\n signal,\n isExpanded,\n signalEdited,\n updateField\n}) => {\n const { field, title } = fieldSpec;\n const htmlFor = `${signal.name}_${field}`;\n let valueCol;\n\n if (isExpanded) {\n let value = signalEdited;\n if (value !== '') {\n const num = Number(value);\n value = isNaN(num) ? '' : num;\n }\n valueCol = (\n <input\n id={htmlFor}\n type=\"number\"\n value={value}\n onChange={(e) => {\n updateField(fieldSpec, e.target.value);\n }}\n />\n );\n } else {\n const value = signal[field];\n valueCol = <span>{value}</span>;\n }\n return (\n <Field\n title={typeof title === 'function' ? title(signal) : title}\n htmlFor={htmlFor}\n >\n {valueCol}\n </Field>\n );\n};\n","import React from 'react';\nimport Field from './Field';\n\nimport { swapKeysAndValues } from '../../utils/object';\n\nexport default ({\n fieldSpec,\n signal,\n isExpanded,\n signalEdited,\n updateField\n}) => {\n let valueCol;\n const { field, title } = fieldSpec;\n const htmlFor = `${signal.name}_${field}`;\n const { options, optionValues } = fieldSpec.options;\n const valueOptions = swapKeysAndValues(optionValues);\n\n if (isExpanded) {\n const optionEles = options.map((opt) => (\n <option key={opt} value={optionValues[opt]}>\n {opt}\n </option>\n ));\n valueCol = (\n <select\n id={htmlFor}\n defaultValue={signalEdited}\n onChange={(e) => {\n updateField(fieldSpec, e.target.value === 'true');\n }}\n >\n {optionEles}\n </select>\n );\n } else {\n valueCol = <span>{valueOptions[signal[field]]}</span>;\n }\n\n return (\n <Field\n title={typeof title === 'function' ? title(signal) : title}\n htmlFor={htmlFor}\n >\n {valueCol}\n </Field>\n );\n};\n","import React from 'react';\nimport Field from './Field';\n\nexport default ({\n fieldSpec,\n signal,\n isExpanded,\n signalEdited,\n updateField\n}) => {\n const { field, title } = fieldSpec;\n const htmlFor = `${signal.name}_${field}`;\n let valueCol;\n if (isExpanded) {\n valueCol = (\n <input\n id={htmlFor}\n type=\"text\"\n value={signalEdited || ''}\n onChange={(e) => {\n updateField(fieldSpec, e.target.value);\n }}\n />\n );\n } else {\n valueCol = <span>{signal[field]}</span>;\n }\n\n return (\n <Field\n title={typeof title === 'function' ? title(signal) : title}\n htmlFor={htmlFor}\n >\n {valueCol}\n </Field>\n );\n};\n","import styled from 'react-emotion';\n\n// color bar on the left side of the signals legend\nexport default styled('div')`\n display: block;\n height: 100%;\n left: 0;\n position: absolute;\n width: 1.5%;\n opacity: ${({ isHighlighted }) => (isHighlighted ? 0.5 : 0.3)};\n background-color: rgb(${({ rgb }) => rgb.join(',')});\n`;\n","// SignalLegendEntry.js\n\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\n\nimport Signal from '../../models/can/signal';\nimport SignalForm from './SignalForm';\nimport ColorBar from './ColorBar';\nimport FIELDS from './FIELDS';\n\nexport default class SignalLegendEntry extends Component {\n static propTypes = {\n isLogEvent: PropTypes.bool,\n signal: PropTypes.instanceOf(Signal).isRequired,\n isHighlighted: PropTypes.bool,\n onSignalHover: PropTypes.func,\n onSignalHoverEnd: PropTypes.func,\n onTentativeSignalChange: PropTypes.func,\n onSignalChange: PropTypes.func,\n onSignalRemove: PropTypes.func,\n onSignalPlotChange: PropTypes.func,\n toggleExpandSignal: PropTypes.func,\n isPlotted: PropTypes.bool,\n isExpanded: PropTypes.bool\n };\n\n static fieldSpecForName = (name) => FIELDS.find((field) => field.field === name);\n\n constructor(props) {\n super(props);\n this.state = {\n signalEdited: Object.assign(Object.create(props.signal), props.signal)\n };\n }\n\n componentWillReceiveProps(nextProps) {\n if (!nextProps.signal.equals(this.props.signal)) {\n this.setState({\n signalEdited: Object.assign(\n Object.create(nextProps.signal),\n nextProps.signal\n )\n });\n }\n }\n\n updateField = (fieldSpec, value) => {\n let { signalEdited } = this.state;\n const { signal } = this.props;\n\n if (fieldSpec.transform) {\n signalEdited = fieldSpec.transform(value, signalEdited);\n } else {\n signalEdited[fieldSpec.field] = value;\n }\n\n // Save entire signal while editing\n this.setState({ signalEdited });\n const signalCopy = Object.assign(Object.create(signal), signal);\n Object.entries(signalEdited).forEach(([field, value]) => {\n signalCopy[field] = value;\n });\n this.props.onSignalChange(signalCopy, signal);\n };\n\n toggleEditing = (e) => {\n if (this.props.isLogEvent) {\n return;\n }\n let { signalEdited } = this.state;\n const { signal, isExpanded } = this.props;\n const signalCopy = Object.assign(Object.create(signal), signal);\n\n if (isExpanded) {\n // Finished editing, save changes & reset intermediate\n // signalEdited state.\n Object.entries(signalEdited).forEach(([field, value]) => {\n const fieldSpec = SignalLegendEntry.fieldSpecForName(field);\n\n if (\n fieldSpec\n && fieldSpec.type === 'number'\n && isNaN(parseInt(value, 10))\n ) {\n value = 0;\n }\n\n signalCopy[field] = value;\n });\n this.props.onSignalChange(signalCopy, signal);\n } else {\n signalEdited = signalCopy;\n }\n\n // Expand and enable signal editing\n this.setState({\n signalEdited\n });\n this.props.toggleExpandSignal(signal);\n e.stopPropagation();\n };\n\n toggleSignalPlot = (e) => {\n const { signal, isPlotted } = this.props;\n e.preventDefault();\n this.props.onSignalPlotChange(!isPlotted, signal.uid);\n };\n\n getSignalEdited = (field) => this.state.signalEdited[field];\n\n render() {\n const {\n signal, isHighlighted, color, isPlotted, isExpanded\n } = this.props;\n const expandedEntryClass = isExpanded ? 'is-expanded' : null;\n const plottedButtonClass = isPlotted ? 'button' : 'button--alpha';\n return (\n <div\n className={cx('signals-legend-entry', expandedEntryClass)}\n onMouseEnter={() => this.props.onSignalHover(signal)}\n onMouseLeave={() => this.props.onSignalHoverEnd(signal)}\n >\n <ColorBar isHighlighted={isHighlighted} rgb={color} />\n <div className=\"signals-legend-entry-header\">\n <div\n className=\"signals-legend-entry-header-name\"\n onClick={this.toggleEditing}\n >\n <strong>{signal.name}</strong>\n </div>\n <div\n className=\"signals-legend-entry-header-action\"\n onClick={this.toggleSignalPlot}\n >\n <button className={cx('button--tiny', plottedButtonClass)}>\n {isPlotted ? 'Hide Plot' : 'Show Plot'}\n </button>\n </div>\n </div>\n <div className=\"signals-legend-entry-body\">\n {isExpanded && (\n <SignalForm\n signal={signal}\n onSignalRemove={this.props.onSignalRemove}\n isExpanded={isExpanded}\n getSignalEdited={this.getSignalEdited}\n update={this.updateField}\n />\n )}\n </div>\n </div>\n );\n }\n}\n","// SignalLegend.js\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nimport SignalLegendEntry from './SignalLegendEntry';\n\nexport default class SignalLegend extends Component {\n static propTypes = {\n isLogEvent: PropTypes.bool,\n signals: PropTypes.object,\n signalStyles: PropTypes.object,\n highlightedSignal: PropTypes.string,\n onSignalHover: PropTypes.func,\n onSignalHoverEnd: PropTypes.func,\n onTentativeSignalChange: PropTypes.func,\n onSignalChange: PropTypes.func,\n onSignalRemove: PropTypes.func,\n onSignalPlotChange: PropTypes.func,\n plottedSignalUids: PropTypes.array,\n selectedMessageKey: PropTypes.string\n };\n\n state = {\n expandedSignals: []\n };\n\n toggleExpandSignal = (s) => {\n const { expandedSignals } = this.state;\n if (!expandedSignals.includes(s.uid)) {\n const updatedExpandedSignals = [...expandedSignals, s.uid];\n this.setState({ expandedSignals: updatedExpandedSignals });\n } else {\n const updatedExpandedSignals = expandedSignals.filter((i) => i !== s.uid);\n this.setState({ expandedSignals: updatedExpandedSignals });\n }\n };\n\n checkExpandedSignal(s) {\n return this.state.expandedSignals.includes(s);\n }\n\n render() {\n const { signals, highlightedSignal, selectedMessageKey } = this.props;\n const signalRowsNested = Object.entries(signals)\n .sort(([_, signal1], [__, signal2]) => {\n if (signal1.startBit < signal2.startBit) {\n return -1;\n }\n return 1;\n })\n .map(([signalName, signal]) => {\n const colors = signals[signalName].getColors(selectedMessageKey);\n const isHighlighted = highlightedSignal === signalName;\n\n return (\n <SignalLegendEntry\n isLogEvent={this.props.isLogEvent}\n key={signal.uid}\n signal={signal}\n isHighlighted={isHighlighted}\n color={colors}\n onSignalHover={this.props.onSignalHover}\n onSignalHoverEnd={this.props.onSignalHoverEnd}\n onTentativeSignalChange={this.props.onTentativeSignalChange}\n onSignalChange={this.props.onSignalChange}\n onSignalRemove={this.props.onSignalRemove}\n onSignalPlotChange={this.props.onSignalPlotChange}\n toggleExpandSignal={this.toggleExpandSignal}\n isPlotted={this.props.plottedSignalUids.indexOf(signal.uid) !== -1}\n isExpanded={this.checkExpandedSignal(signal.uid)}\n />\n );\n });\n\n const signalRows = signalRowsNested\n .filter((row) => row != null)\n .reduce((a, b) => a.concat(b), []);\n\n return <div className=\"cabana-explorer-signals-legend\">{signalRows}</div>;\n }\n}\n","import React, { Component } from 'react';\nimport cx from 'classnames';\nimport PropTypes from 'prop-types';\n\nimport OpenDbc from '../api/OpenDbc';\n\nexport default class GithubDbcList extends Component {\n static propTypes = {\n onDbcLoaded: PropTypes.func.isRequired,\n repo: PropTypes.string.isRequired,\n openDbcClient: PropTypes.instanceOf(OpenDbc).isRequired\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n paths: [],\n selectedPath: null,\n pathQuery: ''\n };\n\n this.updatePathQuery = this.updatePathQuery.bind(this);\n }\n\n componentWillReceiveProps(nextProps) {\n if (nextProps.repo !== this.props.repo) {\n this.props.openDbcClient.list(nextProps.repo).then((paths) => {\n this.setState({ paths, selectedPath: null });\n });\n }\n }\n\n componentDidMount() {\n this.props.openDbcClient.list(this.props.repo).then((paths) => {\n paths = paths.filter((path) => path.indexOf('.dbc') !== -1);\n this.setState({ paths });\n });\n }\n\n updatePathQuery(e) {\n this.setState({\n pathQuery: e.target.value\n });\n }\n\n selectPath(path) {\n this.setState({ selectedPath: path });\n this.props.openDbcClient\n .getDbcContents(path, this.props.repo)\n .then((dbcContents) => {\n this.props.onDbcLoaded(path, dbcContents);\n });\n }\n\n render() {\n return (\n <div className=\"cabana-dbc-list\">\n <div className=\"cabana-dbc-list-header\">\n <a href={`https://github.com/${this.props.repo}`} target=\"_blank\">\n <i className=\"fa fa-github\" />\n <span>{this.props.repo}</span>\n </a>\n <div className=\"form-field form-field--small\">\n <input\n type=\"text\"\n placeholder=\"Search DBC Files\"\n onChange={this.updatePathQuery}\n />\n </div>\n </div>\n <div className=\"cabana-dbc-list-files\">\n {this.state.paths\n .filter(\n (p) => (this.state.pathQuery === '') | p.includes(this.state.pathQuery)\n )\n .map((path) => (\n <div\n className={cx('cabana-dbc-list-file', {\n 'is-selected': this.state.selectedPath === path\n })}\n onClick={() => {\n this.selectPath(path);\n }}\n key={path}\n >\n <span>{path}</span>\n </div>\n ))}\n </div>\n </div>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport default class DbcUpload extends Component {\n static propTypes = {\n onDbcLoaded: PropTypes.func\n };\n\n constructor(props) {\n super(props);\n this.state = {\n dbcText: ''\n };\n\n this.onTextChanged = this.onTextChanged.bind(this);\n }\n\n onTextChanged(e) {\n const dbcText = e.target.value;\n this.setState({ dbcText });\n this.props.onDbcLoaded('from paste', dbcText);\n }\n\n render() {\n return (\n <div className=\"cabana-dbc-upload-raw\">\n <div className=\"form-field\">\n <label htmlFor=\"raw_dbc_upload\">\n <span>Raw DBC File:</span>\n <sup>Paste your DBC text output within this box</sup>\n </label>\n <textarea\n value={this.state.dbcText}\n id=\"raw_dbc_upload\"\n className=\"t-mono\"\n placeholder=\"PASTE DBC FILE HERE\"\n onChange={this.onTextChanged}\n />\n </div>\n </div>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\n\nimport DBC from '../models/can/dbc';\nimport OpenDbc from '../api/OpenDbc';\nimport Modal from './Modals/baseModal';\nimport GithubDbcList from './GithubDbcList';\nimport DbcUpload from './DbcUpload';\n\nexport default class LoadDbcModal extends Component {\n static propTypes = {\n handleClose: PropTypes.func.isRequired,\n onDbcSelected: PropTypes.func.isRequired,\n openDbcClient: PropTypes.instanceOf(OpenDbc).isRequired,\n loginWithGithub: PropTypes.element.isRequired\n };\n\n constructor(props) {\n super(props);\n this.state = {\n tab: 'OpenDBC',\n tabs: ['OpenDBC', 'GitHub', 'Upload'],\n dbc: null,\n dbcSource: null,\n userOpenDbcRepo: null\n };\n\n this.onDbcLoaded = this.onDbcLoaded.bind(this);\n this.handleSave = this.handleSave.bind(this);\n this.renderTabNavigation = this.renderTabNavigation.bind(this);\n this.renderTabContent = this.renderTabContent.bind(this);\n this.renderActions = this.renderActions.bind(this);\n }\n\n componentWillMount() {\n this.props.openDbcClient.getUserOpenDbcFork().then((userOpenDbcRepo) => {\n this.setState({ userOpenDbcRepo });\n });\n }\n\n onDbcLoaded(dbcSource, dbcText) {\n const dbc = new DBC(dbcText);\n this.setState({ dbcSource, dbc });\n }\n\n handleSave() {\n const { dbc, dbcSource } = this.state;\n if (dbc !== null) {\n this.props.onDbcSelected(dbcSource, dbc);\n }\n }\n\n renderTabNavigation() {\n return (\n <div className=\"cabana-tabs-navigation\">\n {this.state.tabs.map((tab) => (\n <a\n className={cx({ 'is-active': this.state.tab === tab })}\n onClick={() => {\n this.setState({ tab });\n }}\n key={tab}\n >\n <span>{tab}</span>\n </a>\n ))}\n </div>\n );\n }\n\n renderTabContent() {\n const { tab } = this.state;\n if (tab === 'OpenDBC') {\n return (\n <GithubDbcList\n onDbcLoaded={this.onDbcLoaded}\n repo=\"commaai/opendbc\"\n openDbcClient={this.props.openDbcClient}\n />\n );\n }\n if (tab === 'GitHub') {\n if (!this.props.openDbcClient.hasAuth()) {\n return this.props.loginWithGithub;\n }\n if (this.state.userOpenDbcRepo === null) {\n return <div>Fork it</div>;\n }\n return (\n <GithubDbcList\n onDbcLoaded={this.onDbcLoaded}\n repo={this.state.userOpenDbcRepo}\n openDbcClient={this.props.openDbcClient}\n />\n );\n }\n if (tab === 'Upload') {\n return <DbcUpload onDbcLoaded={this.onDbcLoaded} />;\n }\n }\n\n renderActions() {\n return (\n <div>\n <button className=\"button--inverted\" onClick={this.props.handleClose}>\n <span>Cancel</span>\n </button>\n <button className=\"button--primary\" onClick={this.handleSave}>\n <span>Load DBC</span>\n </button>\n </div>\n );\n }\n\n render() {\n return (\n <Modal\n title=\"Load DBC File\"\n subtitle=\"Modify an existing DBC file with Cabana\"\n handleClose={this.props.handleClose}\n navigation={this.renderTabNavigation()}\n actions={this.renderActions()}\n >\n {this.renderTabContent()}\n </Modal>\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport default class MessageBytes extends Component {\n static propTypes = {\n seekTime: PropTypes.number.isRequired,\n message: PropTypes.object.isRequired,\n seekIndex: PropTypes.number,\n live: PropTypes.bool.isRequired\n };\n\n constructor(props) {\n super(props);\n this.state = {\n isVisible: true,\n lastMessageIndex: 0,\n lastSeekTime: 0\n };\n\n this.onVisibilityChange = this.onVisibilityChange.bind(this);\n this.onCanvasRefAvailable = this.onCanvasRefAvailable.bind(this);\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n if (nextProps.live) {\n const nextLastEntry = nextProps.message.entries[nextProps.message.entries.length - 1];\n const curLastEntry = this.props.message.entries[\n this.props.message.entries.length - 1\n ];\n\n return nextLastEntry.hexData !== curLastEntry.hexData;\n }\n return nextProps.seekTime !== this.props.seekTime;\n }\n\n componentWillReceiveProps(nextProps) {\n if (\n this.props.seekIndex !== nextProps.seekIndex\n || frameForTime(this.props.seekTime) !== frameForTime(nextProps.seekTime)\n ) {\n this.updateCanvas(nextProps);\n }\n\n function frameForTime(t) {\n return ~~(t * 60);\n }\n }\n\n findMostRecentMessage(seekTime) {\n const { message } = this.props;\n const { lastMessageIndex, lastSeekTime } = this.state;\n let mostRecentMessageIndex = null;\n if (seekTime >= lastSeekTime) {\n for (let i = lastMessageIndex; i < message.entries.length; ++i) {\n const msg = message.entries[i];\n if (msg && msg.relTime >= seekTime) {\n mostRecentMessageIndex = i;\n break;\n }\n }\n }\n\n if (!mostRecentMessageIndex) {\n // TODO this can be faster with binary search, not currently a bottleneck though.\n\n mostRecentMessageIndex = message.entries.findIndex(\n (e) => e.relTime >= seekTime\n );\n }\n\n if (mostRecentMessageIndex) {\n this.setState({\n lastMessageIndex: mostRecentMessageIndex,\n lastSeekTime: seekTime\n });\n return message.entries[mostRecentMessageIndex];\n }\n }\n\n updateCanvas(props) {\n const { message, live, seekTime } = props;\n if (!this.canvas || message.entries.length === 0) return;\n\n let mostRecentMsg = message.entries[message.entries.length - 1];\n if (!live) {\n mostRecentMsg = this.findMostRecentMessage(seekTime);\n\n if (!mostRecentMsg) {\n mostRecentMsg = message.entries[0];\n }\n }\n\n const ctx = this.canvas.getContext('2d');\n // ctx.clearRect(0, 0, 180, 15);\n\n for (let i = 0; i < message.byteStateChangeCounts.length; ++i) {\n const hexData = mostRecentMsg.hexData.substr(i * 2, 2);\n ctx.fillStyle = message.byteColors[i];\n\n ctx.fillRect(i * 20, 0, 20, 15);\n\n ctx.font = '12px Courier';\n ctx.fillStyle = 'white';\n if (hexData) {\n ctx.fillText(hexData, i * 20 + 2, 12);\n } else {\n ctx.fillText('-', i * 20 + 7, 12);\n }\n }\n }\n\n onVisibilityChange(isVisible) {\n if (isVisible !== this.state.isVisible) {\n this.setState({ isVisible });\n }\n }\n\n onCanvasRefAvailable(ref) {\n if (!ref) return;\n\n this.canvas = ref;\n this.canvas.width = 160 * window.devicePixelRatio;\n this.canvas.height = 15 * window.devicePixelRatio;\n const ctx = this.canvas.getContext('2d');\n ctx.scale(window.devicePixelRatio, window.devicePixelRatio);\n }\n\n render() {\n return (\n <canvas\n ref={this.onCanvasRefAvailable}\n className=\"cabana-meta-messages-list-item-bytes-canvas\"\n />\n );\n }\n}\n","import React, { Component } from 'react';\nimport cx from 'classnames';\nimport PropTypes from 'prop-types';\nimport Clipboard from 'clipboard';\n\nimport MessageBytes from './MessageBytes';\n\nconst { ckmeans } = require('simple-statistics');\n\nexport default class Meta extends Component {\n static propTypes = {\n onMessageSelected: PropTypes.func,\n onMessageUnselected: PropTypes.func,\n dongleId: PropTypes.string,\n name: PropTypes.string,\n messages: PropTypes.objectOf(PropTypes.object),\n selectedMessages: PropTypes.array,\n onPartChanged: PropTypes.func,\n partsCount: PropTypes.number,\n showLoadDbc: PropTypes.func,\n showSaveDbc: PropTypes.func,\n dbcFilename: PropTypes.string,\n dbcLastSaved: PropTypes.object, // moment.js object,\n showEditMessageModal: PropTypes.func,\n route: PropTypes.object,\n partsLoaded: PropTypes.number,\n currentParts: PropTypes.array,\n seekTime: PropTypes.number,\n loginWithGithub: PropTypes.element,\n isDemo: PropTypes.bool,\n live: PropTypes.bool\n };\n\n constructor(props) {\n super(props);\n\n this.onFilterChanged = this.onFilterChanged.bind(this);\n this.onFilterFocus = this.onFilterFocus.bind(this);\n this.onFilterUnfocus = this.onFilterUnfocus.bind(this);\n this.canMsgFilter = this.canMsgFilter.bind(this);\n this.logEventMsgFilter = this.logEventMsgFilter.bind(this);\n this.renderMessageBytes = this.renderMessageBytes.bind(this);\n this.toggleShowLogEvents = this.toggleShowLogEvents.bind(this);\n\n const { dbcLastSaved } = props;\n\n this.state = {\n filterText: 'Filter',\n lastSaved:\n dbcLastSaved !== null ? this.props.dbcLastSaved.fromNow() : null,\n hoveredMessages: [],\n orderedMessageKeys: [],\n showLogEvents: false\n };\n }\n\n componentDidMount() {\n this.lastSavedTimer = setInterval(() => {\n if (this.props.dbcLastSaved !== null) {\n this.setState({ lastSaved: this.props.dbcLastSaved.fromNow() });\n }\n }, 30000);\n }\n\n componentWillUnmount() {\n window.clearInterval(this.lastSavedTimer);\n }\n\n componentWillReceiveProps(nextProps) {\n if (\n nextProps.lastSaved !== this.props.lastSaved\n && typeof nextProps === 'object'\n ) {\n this.setState({ lastSaved: nextProps.dbcLastSaved.fromNow() });\n }\n\n const nextMsgKeys = Object.keys(nextProps.messages);\n if (\n JSON.stringify(nextMsgKeys)\n !== JSON.stringify(Object.keys(this.props.messages))\n ) {\n const orderedMessageKeys = this.sortMessages(nextProps.messages);\n this.setState({ hoveredMessages: [], orderedMessageKeys });\n } else if (\n this.state.orderedMessageKeys.length === 0\n || (!this.props.live\n && this.props.messages\n && nextProps.messages\n && this.byteCountsDidUpdate(this.props.messages, nextProps.messages))\n ) {\n const orderedMessageKeys = this.sortMessages(nextProps.messages);\n this.setState({ orderedMessageKeys });\n }\n }\n\n byteCountsDidUpdate(prevMessages, nextMessages) {\n return Object.entries(nextMessages).some(\n ([msgId, msg]) => JSON.stringify(msg.byteStateChangeCounts)\n !== JSON.stringify(prevMessages[msgId].byteStateChangeCounts)\n );\n }\n\n sortMessages(messages) {\n // Returns list of message keys, ordered as follows:\n // messages are binned into at most 10 bins based on entry count\n // each bin is sorted by message CAN address\n // then the list of bins is flattened and reversed to\n // yield a count-descending, address-ascending order.\n\n if (Object.keys(messages).length === 0) return [];\n const messagesByEntryCount = Object.entries(messages).reduce(\n (partialMapping, [msgId, msg]) => {\n const entryCountKey = msg.entries.length.toString(); // js object keys are strings\n if (!partialMapping[entryCountKey]) {\n partialMapping[entryCountKey] = [msg];\n } else {\n partialMapping[entryCountKey].push(msg);\n }\n return partialMapping;\n },\n {}\n );\n\n const entryCounts = Object.keys(messagesByEntryCount).map((count) => parseInt(count, 10));\n const binnedEntryCounts = ckmeans(\n entryCounts,\n Math.min(entryCounts.length, 10)\n );\n const sortedKeys = binnedEntryCounts\n .map((bin) => bin\n .map((entryCount) => messagesByEntryCount[entryCount.toString()])\n .reduce((messages, partial) => messages.concat(partial), [])\n .sort((msg1, msg2) => {\n if (msg1.address < msg2.address) {\n return 1;\n }\n return -1;\n })\n .map((msg) => msg.id))\n .reduce((keys, bin) => keys.concat(bin), [])\n .reverse();\n\n return sortedKeys;\n }\n\n toggleShowLogEvents() {\n this.setState({\n showLogEvents: !this.state.showLogEvents\n });\n }\n\n onFilterChanged(e) {\n let val = e.target.value;\n if (val.trim() === 'Filter') val = '';\n\n this.setState({ filterText: val });\n }\n\n onFilterFocus(e) {\n if (this.state.filterText.trim() === 'Filter') {\n this.setState({ filterText: '' });\n }\n }\n\n onFilterUnfocus(e) {\n if (this.state.filterText.trim() === '') {\n this.setState({ filterText: 'Filter' });\n }\n }\n\n canMsgFilter(msg) {\n if (msg.isLogEvent) {\n return;\n }\n const { filterText } = this.state;\n const msgName = msg.frame ? msg.frame.name : '';\n\n return (\n filterText === 'Filter'\n || filterText === ''\n || msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1\n || msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1\n );\n }\n\n logEventMsgFilter(msg) {\n if (!msg.isLogEvent) {\n return;\n }\n const { filterText } = this.state;\n const msgName = msg.frame ? msg.frame.name : '';\n\n return (\n filterText === 'Filter'\n || filterText === ''\n || msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1\n || msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1\n );\n }\n\n lastSavedPretty() {\n const { dbcLastSaved } = this.props;\n return dbcLastSaved.fromNow();\n }\n\n onMessageHover(key) {\n const { hoveredMessages } = this.state;\n if (hoveredMessages.indexOf(key) !== -1) return;\n\n hoveredMessages.push(key);\n this.setState({ hoveredMessages });\n }\n\n onMessageHoverEnd(key) {\n let { hoveredMessages } = this.state;\n hoveredMessages = hoveredMessages.filter((m) => m !== key);\n this.setState({ hoveredMessages });\n }\n\n onMsgRemoveClick(key) {\n let { selectedMessages } = this.state;\n selectedMessages = selectedMessages.filter((m) => m !== key);\n this.props.onMessageUnselected(key);\n this.setState({ selectedMessages });\n }\n\n onMessageSelected(key) {\n // uncomment when we support multiple messages\n // const selectedMessages = this.state.selectedMessages.filter((m) => m !== key);\n const selectedMessages = [];\n selectedMessages.push(key);\n this.props.updateSelectedMessages(selectedMessages);\n this.props.onMessageSelected(key);\n }\n\n orderedMessages() {\n const { orderedMessageKeys } = this.state;\n const { messages } = this.props;\n return orderedMessageKeys.map((key) => messages[key]);\n }\n\n selectedMessageClass(messageId) {\n return this.props.selectedMessages.includes(messageId)\n ? 'is-selected'\n : null;\n }\n\n renderMessageBytes(msg) {\n return (\n <tr\n onClick={() => {\n this.onMessageSelected(msg.id);\n }}\n key={msg.id}\n className={cx(\n 'cabana-meta-messages-list-item',\n this.selectedMessageClass(msg.id)\n )}\n >\n {msg.isLogEvent ? (\n <td colSpan=\"2\">{msg.id}</td>\n ) : (\n <>\n <td>{msg.frame ? msg.frame.name : 'untitled'}</td>\n <td>{msg.id}</td>\n </>\n )}\n <td>{msg.entries.length}</td>\n <td>\n <div className=\"cabana-meta-messages-list-item-bytes\">\n <MessageBytes\n key={msg.id}\n message={msg}\n seekIndex={this.props.seekIndex}\n seekTime={this.props.seekTime}\n live={this.props.live}\n />\n </div>\n </td>\n </tr>\n );\n }\n\n renderCanMessages() {\n return this.orderedMessages()\n .filter(this.canMsgFilter)\n .map(this.renderMessageBytes);\n }\n\n renderLogEventMessages() {\n return this.orderedMessages()\n .filter(this.logEventMsgFilter)\n .map(this.renderMessageBytes);\n }\n\n renderAvailableMessagesList() {\n if (Object.keys(this.props.messages).length === 0) {\n return <p>Loading messages...</p>;\n }\n return (\n <>\n <table cellPadding=\"5\">\n {this.state.showLogEvents && (\n <>\n <thead>\n <tr>\n <td colSpan=\"2\">Name</td>\n <td>Count</td>\n <td>Bytes</td>\n </tr>\n </thead>\n <tbody>\n {this.renderLogEventMessages()}\n <tr>\n <td colSpan=\"4\">\n <hr />\n </td>\n </tr>\n </tbody>\n </>\n )}\n <thead>\n <tr>\n <td>Name</td>\n <td>ID</td>\n <td>Count</td>\n <td>Bytes</td>\n </tr>\n </thead>\n <tbody>{this.renderCanMessages()}</tbody>\n </table>\n </>\n );\n }\n\n saveable() {\n try {\n // eslint-disable-next-line\n \"serviceWorker\" in navigator &&\n !!new ReadableStream()\n && !!new WritableStream(); // eslint-disable-line no-undef\n return 'saveable';\n } catch (e) {\n return false;\n }\n }\n\n render() {\n return (\n <div className=\"cabana-meta\">\n <div className=\"cabana-meta-header\">\n <h5 className=\"cabana-meta-header-label t-capline\">\n Currently editing:\n </h5>\n <strong className=\"cabana-meta-header-filename\">\n {this.props.dbcFilename}\n </strong>\n {this.props.dbcLastSaved !== null ? (\n <div className=\"cabana-meta-header-last-saved\">\n <p>\n Last saved:\n {this.lastSavedPretty()}\n </p>\n </div>\n ) : null}\n <div className={`cabana-meta-header-actions ${this.saveable()}`}>\n <div className=\"cabana-meta-header-action\">\n <button onClick={this.props.showLoadDbc}>Load DBC</button>\n </div>\n {this.saveable() && (\n <div className=\"cabana-meta-header-action\">\n <button onClick={this.props.saveLog}>Save Log</button>\n </div>\n )}\n {this.props.shareUrl ? (\n <div\n className=\"cabana-meta-header-action special-wide\"\n data-clipboard-text={this.props.shareUrl}\n data-clipboard-action=\"copy\"\n ref={(ref) => (ref ? new Clipboard(ref) : null)}\n >\n <a\n className=\"button\"\n href={this.props.shareUrl}\n onClick={(e) => e.preventDefault()}\n >\n Copy Share Link\n </a>\n </div>\n ) : null}\n <div className=\"cabana-meta-header-action\">\n <button onClick={this.props.showSaveDbc}>Save DBC</button>\n </div>\n </div>\n </div>\n <div className=\"cabana-meta-messages\">\n <div className=\"cabana-meta-messages-header\">\n <div\n style={{\n display: 'inline-block',\n float: 'right'\n }}\n >\n <h5 className=\"t-capline\">\n Show log events\n <input\n type=\"checkbox\"\n onChange={this.toggleShowLogEvents}\n checked={!!this.state.showLogEvents}\n />\n </h5>\n </div>\n <h5 className=\"t-capline\">Available messages</h5>\n </div>\n <div className=\"cabana-meta-messages-window\">\n <div className=\"cabana-meta-messages-filter\">\n <div className=\"form-field form-field--small\">\n <input\n type=\"text\"\n value={this.state.filterText}\n onFocus={this.onFilterFocus}\n onBlur={this.onFilterUnfocus}\n onChange={this.onFilterChanged}\n />\n </div>\n </div>\n <div className=\"cabana-meta-messages-list\">\n {this.renderAvailableMessagesList()}\n </div>\n </div>\n </div>\n </div>\n );\n }\n}\n","import init from './init';\nimport './index.css';\n\ninit();\n","import DBC from '../models/can/dbc';\n\nexport function fetchPersistedDbc(routeName) {\n const maybeDbc = window.localStorage.getItem(routeName);\n if (maybeDbc !== null) {\n const { dbcFilename, dbcText } = JSON.parse(maybeDbc);\n const dbc = new DBC(dbcText);\n\n return { dbc, dbcText, dbcFilename };\n }\n return null;\n}\n\nexport function persistDbc(routeName, { dbcFilename, dbc }) {\n const dbcJson = JSON.stringify({\n dbcFilename,\n dbcText: dbc.text()\n });\n window.localStorage.setItem(routeName, dbcJson);\n}\n\nconst GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = 'gh_auth_token';\nexport function fetchPersistedGithubAuthToken() {\n return window.localStorage.getItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY);\n}\n\nexport function unpersistGithubAuthToken() {\n window.localStorage.removeItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY);\n}\n\nexport function persistGithubAuthToken(token) {\n return window.localStorage.setItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY, token);\n}\n","export default function debounce(func, wait, immediate) {\n let timeout;\n return function () {\n const context = this;\n const args = arguments;\n const later = function () {\n timeout = null;\n if (!immediate) func.apply(context, args);\n };\n const callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) func.apply(context, args);\n };\n}\n","import randomcolor from 'randomcolor';\nimport DbcUtils from '../../utils/dbc';\n\nexport default class Signal {\n constructor({\n name,\n startBit = 0,\n size = 0,\n isLittleEndian = true,\n isSigned = false,\n isFloat = false,\n factor = 1,\n offset = 0,\n unit = '',\n receiver = ['XXX'],\n comment = null,\n multiplex = null,\n min = null,\n max = null,\n valueDescriptions = new Map()\n }) {\n Object.assign(this, {\n name,\n startBit,\n size,\n isLittleEndian,\n isSigned,\n isFloat,\n factor,\n offset,\n unit,\n receiver,\n comment,\n multiplex,\n valueDescriptions\n });\n\n const uid = Math.random().toString(36);\n\n if (min == null) {\n min = this.calculateMin();\n }\n if (max == null) {\n max = this.calculateMax();\n }\n\n const colors = this.generateColors();\n\n Object.assign(this, {\n min,\n max,\n uid,\n _colors: colors\n });\n\n Object.defineProperty(this, 'colors', {\n get() {\n console.error('Something is still using the old colors');\n debugger;\n return colors;\n },\n enumberable: false\n });\n }\n\n text() {\n const multiplex = this.multiplex ? ` ${this.multiplex}` : '';\n const byteOrder = this.isLittleEndian ? 1 : 0;\n const signedChar = this.isSigned ? '-' : '+';\n\n return (\n `SG_ ${this.name}${multiplex} : `\n + `${this.startBit}|${this.size}@${byteOrder}${signedChar}`\n + ` (${this.factor},${this.offset})`\n + ` [${this.min}|${this.max}]`\n + ` \"${this.unit}\" ${this.receiver}`\n );\n }\n\n valueDescriptionText(msgId) {\n const entryPairs = Array.from(this.valueDescriptions.entries());\n const values = entryPairs.reduce(\n (str, [value, desc]) => `${str + value} \"${desc}\" `,\n ''\n );\n return `VAL_ ${msgId} ${this.name} ${values};`;\n }\n\n lsbBitIndex() {\n // Returns LSB bit index in matrix order (see AddSignals.js)\n\n if (this.isLittleEndian) {\n return this.startBit;\n }\n const lsbBitNumber = this.lsbBitNumber();\n\n return DbcUtils.matrixBitNumber(lsbBitNumber);\n }\n\n lsbBitNumber() {\n // Returns LSB bit number in big endian ordering\n\n return DbcUtils.bigEndianBitIndex(this.startBit) + this.size - 1;\n }\n\n msbBitIndex() {\n if (this.isLittleEndian) {\n return this.startBit + this.size - 1;\n }\n return this.startBit;\n }\n\n littleEndianBitDescription(bitIndex) {\n const bitRange = [this.startBit, this.startBit + this.size - 1];\n if (bitIndex < bitRange[0] || bitIndex > bitRange[1]) {\n return null;\n }\n const bitNumber = bitIndex - bitRange[0];\n const isLsb = bitIndex === bitRange[0];\n const isMsb = bitIndex === bitRange[1];\n return { bitNumber, isLsb, isMsb };\n }\n\n bigEndianBitDescription(bitIndex) {\n const start = DbcUtils.bigEndianBitIndex(this.startBit);\n const range = [start, start + this.size - 1];\n const bitNumber = DbcUtils.bigEndianBitIndex(bitIndex);\n\n if (bitNumber < range[0] || bitNumber > range[1]) {\n return null;\n }\n\n const isLsb = bitNumber === range[1];\n const isMsb = bitIndex === this.startBit;\n return {\n bitNumber,\n isLsb,\n isMsb,\n range\n };\n }\n\n bitDescription(bitIndex) {\n if (this.isLittleEndian) {\n return this.littleEndianBitDescription(bitIndex);\n }\n return this.bigEndianBitDescription(bitIndex);\n }\n\n calculateRawRange() {\n let rawRange = Math.pow(2, this.size);\n if (this.isSigned) {\n rawRange /= 2;\n }\n return [this.isSigned ? -1 * rawRange : 0, rawRange - 1];\n }\n\n calculateMin() {\n const rawMin = this.calculateRawRange()[0];\n return this.offset + rawMin * this.factor;\n }\n\n calculateMax() {\n const rawMax = this.calculateRawRange()[1];\n return this.offset + rawMax * this.factor;\n }\n\n getColors(messageId) {\n let parts = messageId.split(':').map((p) => ((3 + Number.parseInt(p, 16)) * 3) % 253);\n const colors = this._colors || this.generateColors();\n\n let lastColor = 0;\n\n return colors.map((c) => {\n parts = parts.map(p => p ^ lastColor);\n lastColor = parts.reduce((m, v) => m ^ v, c);\n return lastColor;\n });\n }\n\n generateColors() {\n const colors = randomcolor({ format: 'rgbArray' });\n\n return colors;\n }\n\n equals(otherSignal) {\n return (\n otherSignal.name === this.name\n && otherSignal.startBit === this.startBit\n && otherSignal.size === this.size\n && otherSignal.isLittleEndian === this.isLittleEndian\n && otherSignal.isSigned === this.isSigned\n && otherSignal.isFloat === this.isFloat\n && otherSignal.factor === this.factor\n && otherSignal.offset === this.offset\n && otherSignal.unit === this.unit\n && otherSignal.receiver.length === this.receiver.length\n && otherSignal.receiver.every((v, i) => v === this.receiver[i])\n && otherSignal.comment === this.comment\n && otherSignal.multiplex === this.multiplex\n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\nimport Measure from 'react-measure';\n\nexport default class Modal extends Component {\n static propTypes = {\n variations: PropTypes.array,\n disableClose: PropTypes.bool,\n handleClose: PropTypes.func,\n handleSave: PropTypes.func,\n title: PropTypes.string,\n subtitle: PropTypes.string,\n navigation: PropTypes.node,\n actions: PropTypes.node,\n footer: PropTypes.node\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n windowHeight: {},\n modalHeight: {}\n };\n\n this.updateHeights = this.updateHeights.bind(this);\n }\n\n updateHeights(contentRect) {\n this.setState({ windowHeight: window.innerHeight });\n this.setState({ modalHeight: contentRect.bounds.height });\n }\n\n readVariationClasses() {\n if (this.props.variations) {\n const { variations } = this.props;\n const classes = variations.reduce(\n (classes, variation) => `${classes}cabana-modal--${variation} `,\n ''\n );\n return classes;\n }\n }\n\n checkClosability() {\n return this.props.disableClose || false;\n }\n\n checkYScrollability() {\n return this.state.modalHeight > this.state.windowHeight;\n }\n\n render() {\n return (\n <div\n className={cx('cabana-modal', this.readVariationClasses(), {\n 'cabana-modal--not-closable': this.checkClosability(),\n 'cabana-modal--scrollable-y': this.checkYScrollability()\n })}\n >\n <Measure\n bounds\n onResize={(contentRect) => {\n this.updateHeights(contentRect);\n }}\n >\n {({ measureRef }) => (\n <div ref={measureRef} className=\"cabana-modal-container\">\n <div\n className=\"cabana-modal-close-icon\"\n onClick={this.props.handleClose}\n />\n <div className=\"cabana-modal-header\">\n <h1>{this.props.title}</h1>\n <p>{this.props.subtitle}</p>\n </div>\n <div className=\"cabana-modal-navigation\">\n {this.props.navigation}\n </div>\n <div className=\"cabana-modal-body\">\n <div className=\"cabana-modal-body-window\">\n {this.props.children}\n </div>\n <div className=\"cabana-modal-body-gradient\" />\n </div>\n <div className=\"cabana-modal-actions\">{this.props.actions}</div>\n <div className=\"cabana-modal-footer\">{this.props.footer}</div>\n </div>\n )}\n </Measure>\n <div\n className=\"cabana-modal-backdrop\"\n onClick={this.props.handleClose}\n />\n </div>\n );\n }\n}\n","module.exports = __webpack_public_path__ + \"static/media/webusb-enable-experimental-features.e5a08e76.png\";","module.exports = __webpack_public_path__ + \"static/media/webusb-enable-webusb.aceef6a0.png\";","module.exports = function() {\n return new Worker(__webpack_public_path__ + \"beaf0312537cf2a84ceb.worker.js\");\n};","module.exports = function() {\n return new Worker(__webpack_public_path__ + \"66fe2b555037a721fc00.worker.js\");\n};","module.exports = function() {\n return new Worker(__webpack_public_path__ + \"83feda798dbec03978d2.worker.js\");\n};","module.exports = function() {\n return new Worker(__webpack_public_path__ + \"c7de2d6e38fac0f21bad.worker.js\");\n};","import DBC from './models/can/dbc';\n\nconst AcuraDbc = new DBC(`\nVERSION \"\"\n\n\nNS_ :\n NS_DESC_\n CM_\n BA_DEF_\n BA_\n VAL_\n CAT_DEF_\n CAT_\n FILTER\n BA_DEF_DEF_\n EV_DATA_\n ENVVAR_DATA_\n SGTYPE_\n SGTYPE_VAL_\n BA_DEF_SGTYPE_\n BA_SGTYPE_\n SIG_TYPE_REF_\n VAL_TABLE_\n SIG_GROUP_\n SIG_VALTYPE_\n SIGTYPE_VALTYPE_\n BO_TX_BU_\n BA_DEF_REL_\n BA_REL_\n BA_DEF_DEF_REL_\n BU_SG_REL_\n BU_EV_REL_\n BU_BO_REL_\n SG_MUL_VAL_\n\nBS_:\n\nBU_: INTERCEPTOR EBCM NEO ADAS PCM EPS VSA SCM BDY XXX\n\n\nBO_ 57 XXX_1: 3 XXX\n\nBO_ 145 XXX_2: 8 XXX\n SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] \"m/s2\" NEO\n\nBO_ 228 STEERING_CONTROL: 5 ADAS\n SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] \"\" EPS\n SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] \"\" EPS\n SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|0] \"\" EPS\n SG_ COUNTER : 37|2@0+ (1,0) [0|3] \"\" EPS\n SG_ CHECKSUM : 35|4@0+ (1,0) [0|3] \"\" EPS\n\nBO_ 304 GAS_PEDAL2: 8 PCM\n SG_ ENGINE_TORQUE_ESTIMATE : 7|16@0- (1,0) [-1000|1000] \"Nm\" NEO\n SG_ ENGINE_TORQUE_REQUEST : 23|16@0- (1,0) [-1000|1000] \"Nm\" NEO\n SG_ CAR_GAS : 39|8@0+ (1,0) [0|255] \"\" NEO\n\nBO_ 316 GAS_PEDAL: 8 PCM\n SG_ CAR_GAS : 39|8@0+ (1,0) [0|255] \"\" NEO\n\nBO_ 342 STEERING_SENSORS: 6 EPS\n SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] \"deg\" NEO\n SG_ STEER_ANGLE_RATE : 23|16@0- (1,0) [-3000|3000] \"deg/s\" NEO\n SG_ COUNTER : 45|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 344 POWERTRAIN_DATA: 8 PCM\n SG_ XMISSION_SPEED : 7|16@0+ (0.002759506,0) [0|70] \"m/s\" NEO\n SG_ ENGINE_RPM : 23|16@0+ (1,0) [0|15000] \"rpm\" NEO\n SG_ XMISSION_SPEED2 : 39|16@0+ (0.002759506,0) [0|70] \"m/s\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n SG_ ODOMETER : 55|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 380 POWERTRAIN_DATA2: 8 PCM\n SG_ PEDAL_GAS : 7|8@0+ (1,0) [0|255] \"\" NEO\n SG_ ENGINE_RPM : 23|16@0+ (1,0) [0|15000] \"rpm\" NEO\n SG_ GAS_PRESSED : 39|1@0+ (1,0) [0|1] \"\" NEO\n SG_ ACC_STATUS : 38|1@0+ (1,0) [0|1] \"rpm\" NEO\n SG_ BOH_17C : 37|5@0+ (1,0) [0|1] \"rpm\" NEO\n SG_ BRAKE_SWITCH : 32|1@0+ (1,0) [0|1] \"rpm\" NEO\n SG_ BOH2_17C : 47|10@0+ (1,0) [0|1] \"rpm\" NEO\n SG_ BRAKE_PRESSED : 53|1@0+ (1,0) [0|1] \"\" NEO\n SG_ BOH3_17C : 52|5@0+ (1,0) [0|1] \"rpm\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 398 XXX_3: 3 XXX\n\nBO_ 399 STEER_STATUS: 7 EPS\n SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] \"tbd\" NEO\n SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] \"tbd\" NEO\n SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] \"\" NEO\n SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] \"\" NEO\n SG_ COUNTER : 53|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 419 GEARBOX: 8 PCM\n SG_ GEAR : 7|8@0+ (1,0) [0|256] \"\" NEO\n SG_ GEAR_SHIFTER : 35|4@0+ (1,0) [0|15] \"\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 420 VSA_STATUS: 8 VSA\n SG_ USER_BRAKE : 7|16@0+ (0.015625,-1.609375) [0|1000] \"\" NEO\n SG_ ESP_DISABLED : 28|1@0+ (1,0) [0|1] \"\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 422 SCM_BUTTONS: 8 SCM\n SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] \"\" NEO\n SG_ LIGHTS_SETTING : 1|2@0+ (1,0) [0|3] \"\" NEO\n SG_ MAIN_ON : 47|1@0+ (1,0) [0|1] \"\" NEO\n SG_ CRUISE_SETTING : 43|2@0+ (1,0) [0|3] \"\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 428 XXX_4: 8 XXX\n\nBO_ 432 STANDSTILL: 7 VSA\n SG_ WHEELS_MOVING : 12|1@0+ (1,0) [0|1] \"\" NEO\n SG_ BRAKE_ERROR_1 : 11|1@0+ (1,0) [0|1] \"\" NEO\n SG_ BRAKE_ERROR_2 : 9|1@0+ (1,0) [0|1] \"\" NEO\n SG_ COUNTER : 53|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 464 WHEEL_SPEEDS: 8 VSA\n SG_ WHEEL_SPEED_FL : 7|15@0+ (0.002759506,0) [0|70] \"m/s\" NEO\n SG_ WHEEL_SPEED_FR : 8|15@0+ (0.002759506,0) [0|70] \"m/s\" NEO\n SG_ WHEEL_SPEED_RL : 25|15@0+ (0.002759506,0) [0|70] \"m/s\" NEO\n SG_ WHEEL_SPEED_RR : 42|15@0+ (0.002759506,0) [0|70] \"m/s\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 476 XXX_5: 4 XXX\n\nBO_ 490 VEHICLE_DYNAMICS: 8 VSA\n SG_ LONG_ACCEL : 23|16@0- (0.0015384,0) [-20|20] \"m/s2\" NEO\n\nBO_ 506 BRAKE_COMMAND: 8 ADAS\n SG_ COMPUTER_BRAKE : 7|10@0+ (0.003906248,0) [0|1] \"\" EBCM\n SG_ ZEROS_BOH : 13|5@0+ (1,0) [0|1] \"\" EBCM\n SG_ COMPUTER_BRAKE_REQUEST : 8|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_BOH2 : 23|3@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_OVERRIDE : 20|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_BOH3 : 19|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_FAULT_CMD : 18|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_CANCEL_CMD : 17|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ COMPUTER_BRAKE_REQUEST_2 : 16|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_BOH4 : 31|8@0+ (1,0) [0|1] \"\" EBCM\n SG_ BRAKE_LIGHTS : 39|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ CRUISE_BOH5 : 38|7@0+ (1,0) [0|1] \"\" EBCM\n SG_ CHIME : 47|3@0+ (1,0) [0|7] \"\" EBCM\n SG_ CRUISE_BOH6 : 44|1@0+ (1,0) [0|1] \"\" EBCM\n SG_ FCW : 43|2@0+ (1,0) [0|3] \"\" EBCM\n SG_ CRUISE_BOH7 : 41|10@0+ (1,0) [0|0] \"\" EBCM\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" EBCM\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" EBCM\n\nBO_ 512 GAS_COMMAND: 3 NEO\n SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] \"\" INTERCEPTOR\n SG_ COUNTER : 21|2@0+ (1,0) [0|3] \"\" INTERCEPTOR\n SG_ CHECKSUM : 19|4@0+ (1,0) [0|3] \"\" INTERCEPTOR\n\nBO_ 513 GAS_SENSOR: 5 INTERCEPTOR\n SG_ INTERCEPTOR_GAS : 7|16@0+ (0.253984064,-83.3) [0|1] \"\" NEO\n SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.126992032,-83.3) [0|1] \"\" NEO\n SG_ COUNTER : 37|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 35|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 542 XXX_6: 7 XXX\n\nBO_ 545 XXX_7: 4 XXX\n\nBO_ 597 ROUGH_WHEEL_SPEED: 8 VSA\n SG_ WHEEL_SPEED_FL : 7|8@0+ (1,0) [0|255] \"mph\" NEO\n SG_ WHEEL_SPEED_FR : 15|8@0+ (1,0) [0|255] \"mph\" NEO\n SG_ WHEEL_SPEED_RL : 23|8@0+ (1,0) [0|255] \"mph\" NEO\n SG_ WHEEL_SPEED_RR : 31|8@0+ (1,0) [0|255] \"mph\" NEO\n SG_ SET_TO_X55 : 47|8@0+ (1,0) [0|255] \"\" NEO\n\nBO_ 660 SCM_COMMANDS: 8 SCM\n SG_ RIGHT_BLINKER : 6|1@0+ (1,0) [0|1] \"\" NEO\n SG_ LEFT_BLINKER : 5|1@0+ (1,0) [0|1] \"\" NEO\n SG_ WIPERS_SPEED : 4|2@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 773 SEATBELT_STATUS: 7 BDY\n SG_ SEATBELT_DRIVER_LAMP : 7|1@0+ (1,0) [0|1] \"\" NEO\n SG_ SEATBELT_DRIVER_LATCHED : 13|1@0+ (1,0) [0|1] \"\" NEO\n SG_ COUNTER : 53|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 777 XXX_8: 8 XXX\n\nBO_ 780 ACC_HUD: 8 ADAS\n SG_ PCM_SPEED : 7|16@0+ (0.002763889,0) [0|100] \"m/s\" BDY\n SG_ PCM_GAS : 23|7@0+ (1,0) [0|127] \"\" BDY\n SG_ ZEROS_BOH : 16|1@0+ (1,0) [0|255] \"\" BDY\n SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] \"\" BDY\n SG_ DTC_MODE : 39|1@0+ (1,0) [0|1] \"\" BDY\n SG_ BOH : 38|1@0+ (1,0) [0|1] \"\" BDY\n SG_ ACC_PROBLEM : 37|1@0+ (1,0) [0|1] \"\" BDY\n SG_ FCM_OFF : 36|1@0+ (1,0) [0|1] \"\" BDY\n SG_ BOH_2 : 35|1@0+ (1,0) [0|1] \"\" BDY\n SG_ FCM_PROBLEM : 34|1@0+ (1,0) [0|1] \"\" BDY\n SG_ RADAR_OBSTRUCTED : 33|1@0+ (1,0) [0|1] \"\" BDY\n SG_ ENABLE_MINI_CAR : 32|1@0+ (1,0) [0|1] \"\" BDY\n SG_ SET_ME_X03 : 47|2@0+ (1,0) [0|3] \"\" BDY\n SG_ HUD_LEAD : 45|2@0+ (1,0) [0|3] \"\" BDY\n SG_ BOH_3 : 43|1@0+ (1,0) [0|3] \"\" BDY\n SG_ BOH_4 : 42|1@0+ (1,0) [0|3] \"\" BDY\n SG_ BOH_5 : 41|1@0+ (1,0) [0|3] \"\" BDY\n SG_ CRUISE_CONTROL_LABEL : 40|1@0+ (1,0) [0|3] \"\" BDY\n SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] \"\" BDY\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" BDY\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" BDY\n\nBO_ 800 XXX_9: 8 XXX\n\nBO_ 804 CRUISE: 8 PCM\n SG_ HUD_SPEED_KPH : 7|8@0+ (1,0) [0|255] \"kph\" NEO\n SG_ HUD_SPEED_MPH : 15|8@0+ (1,0) [0|255] \"mph\" NEO\n SG_ TRIP_FUEL_CONSUMED : 23|16@0+ (1,0) [0|255] \"\" NEO\n SG_ CRUISE_SPEED_PCM : 39|8@0+ (1,0) [0|255] \"\" NEO\n SG_ BOH2 : 47|8@0- (1,0) [0|255] \"\" NEO\n SG_ BOH3 : 55|8@0+ (1,0) [0|255] \"\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 808 XXX_10: 8 XXX\n\nBO_ 819 XXX_11: 7 XXX\n\nBO_ 821 XXX_12: 5 XXX\n\nBO_ 829 LKAS_HUD_2: 5 ADAS\n SG_ CAM_TEMP_HIGH : 7|1@0+ (1,0) [0|255] \"\" BDY\n SG_ BOH : 23|2@0+ (1,0) [0|4] \"\" BDY\n SG_ DASHED_LANES : 14|1@0+ (1,0) [0|1] \"\" BDY\n SG_ DTC : 13|1@0+ (1,0) [0|1] \"\" BDY\n SG_ LKAS_PROBLEM : 12|1@0+ (1,0) [0|1] \"\" BDY\n SG_ LKAS_OFF : 11|1@0+ (1,0) [0|1] \"\" BDY\n SG_ SOLID_LANES : 10|1@0+ (1,0) [0|1] \"\" BDY\n SG_ LDW_RIGHT : 9|1@0+ (1,0) [0|1] \"\" BDY\n SG_ STEERING_REQUIRED : 8|1@0+ (1,0) [0|1] \"\" BDY\n SG_ LDW_PROBLEM : 21|1@0+ (1,0) [0|1] \"\" BDY\n SG_ BEEP : 17|2@0+ (1,0) [0|1] \"\" BDY\n SG_ LDW_ON : 28|1@0+ (1,0) [0|1] \"\" BDY\n SG_ LDW_OFF : 27|1@0+ (1,0) [0|1] \"\" BDY\n SG_ CLEAN_WINDSHIELD : 26|1@0+ (1,0) [0|1] \"\" BDY\n SG_ SET_ME_X48 : 31|8@0+ (1,0) [0|255] \"\" BDY\n SG_ COUNTER : 37|2@0+ (1,0) [0|3] \"\" BDY\n SG_ CHECKSUM : 35|4@0+ (1,0) [0|3] \"\" BDY\n\nBO_ 882 XXX_13: 2 XXX\n\nBO_ 884 XXX_14: 7 XXX\n\nBO_ 887 XXX_15: 8 XXX\n\nBO_ 888 XXX_16: 8 XXX\n\nBO_ 892 CRUISE_PARAMS: 8 PCM\n SG_ CRUISE_SPEED_OFFSET : 31|8@0- (0.1,0) [-128|127] \"kph\" NEO\n\nBO_ 923 XXX_18: 2 XXX\n\nBO_ 929 XXX_19: 4 XXX\n\nBO_ 983 XXX_20: 8 XXX\n\nBO_ 985 XXX_21: 3 XXX\n\nBO_ 1024 XXX_22: 5 XXX\n\nBO_ 1027 XXX_23: 5 XXX\n\nBO_ 1029 DOORS_STATUS: 8 BDY\n SG_ DOOR_OPEN_FL : 37|1@0+ (1,0) [0|1] \"\" NEO\n SG_ DOOR_OPEN_FR : 38|1@0+ (1,0) [0|1] \"\" NEO\n SG_ DOOR_OPEN_RL : 39|1@0+ (1,0) [0|1] \"\" NEO\n SG_ DOOR_OPEN_RR : 40|1@0+ (1,0) [0|1] \"\" NEO\n SG_ COUNTER : 61|2@0+ (1,0) [0|3] \"\" NEO\n SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] \"\" NEO\n\nBO_ 1030 XXX_24: 5 VSA\n\nBO_ 1034 XXX_25: 5 XXX\n\nBO_ 1036 XXX_26: 8 XXX\n\nBO_ 1039 XXX_27: 8 XXX\n\nBO_ 1057 XXX_28: 5 EPS\n\nBO_ 1064 XXX_29: 7 XXX\n\nBO_ 1108 XXX_30: 8 XXX\n\nBO_ 1365 XXX_31: 5 XXX\n\nBO_ 1600 XXX_32: 5 XXX\n\nBO_ 1601 XXX_33: 8 XXX\n\nBO_TX_BU_ 228 : NEO,ADAS;\nBO_TX_BU_ 506 : NEO,ADAS;\nBO_TX_BU_ 780 : NEO,ADAS;\nBO_TX_BU_ 829 : NEO,ADAS;\n\nCM_ SG_ 419 GEAR \"10 = reverse, 11 = transition\";\nCM_ SG_ 490 LONG_ACCEL \"wheel speed derivative, noisy and zero snapping\";\nCM_ SG_ 780 CRUISE_SPEED \"255 = no speed\";\nCM_ SG_ 804 CRUISE_SPEED_PCM \"255 = no speed\";\nCM_ SG_ 829 BEEP \"beeps are pleasant, chimes are for warnngs etc...\";\nVAL_ 399 STEER_STATUS 5 \"fault\" 4 \"no_torque_alert_2\" 2 \"no_torque_alert_1\" 0 \"normal\" ;\nVAL_ 419 GEAR_SHIFTER 10 \"S\" 4 \"D\" 3 \"N\" 2 \"R\" 1 \"P\" ;\nVAL_ 422 CRUISE_BUTTONS 7 \"tbd\" 6 \"tbd\" 5 \"tbd\" 4 \"accel_res\" 3 \"decel_set\" 2 \"cancel\" 1 \"main\" 0 \"none\" ;\nVAL_ 422 LIGHTS_SETTING 3 \"high_beam\" 2 \"low_beam\" 1 \"position\" 0 \"no_lights\" ;\nVAL_ 422 CRUISE_SETTING 3 \"distance_adj\" 2 \"tbd\" 1 \"lkas_button\" 0 \"none\" ;\nVAL_ 506 CHIME 4 \"double_chime\" 3 \"single_chime\" 2 \"continuous_chime\" 1 \"repeating_chime\" 0 \"no_chime\" ;\nVAL_ 506 FCW 3 \"fcw\" 2 \"fcw\" 1 \"fcw\" 0 \"no_fcw\" ;\nVAL_ 780 HUD_LEAD 3 \"no_car\" 2 \"solid_car\" 1 \"dashed_car\" 0 \"no_car\" ;\nVAL_ 829 BEEP 3 \"single_beep\" 2 \"triple_beep\" 1 \"repeated_beep\" 0 \"no_beep\" ;\n\nCM_ \"CHFFR_METRIC 342 STEER_ANGLE STEER_ANGLE 0.36 180; CHFFR_METRIC 380 ENGINE_RPM ENGINE_RPM 1 0; CHFFR_METRIC 804 ENGINE_TEMPERATURE ENGINE_TEMPERATURE 1 0\";\n`);\n\nexport default AcuraDbc;\n","import GitHub from 'github-api';\n\nimport { OPENDBC_SOURCE_REPO } from '../config';\n\nexport default class OpenDBC {\n constructor(token) {\n this.token = token;\n this.github = new GitHub({ token });\n this.sourceRepo = this.github.getRepo('commaai', 'opendbc');\n this.githubUsername = null;\n }\n\n hasAuth() {\n return this.token !== null;\n }\n\n async getGithubUsername() {\n if (this.githubUsername) {\n return this.githubUsername;\n }\n const githubUsername = await this.fetchGithubUsername();\n if (githubUsername) {\n return githubUsername;\n }\n }\n\n async fetchGithubUsername() {\n try {\n const user = await this.github.getUser();\n if (user) {\n const profile = await user.getProfile();\n if (profile) {\n return profile.data.login;\n }\n }\n } catch (e) {\n return null;\n }\n }\n\n async list(repoFullName) {\n /*\n Lists files in a github repository.\n If no argument provided, assumes OpenDBC source repo\n (commaai/opendbc)\n */\n\n let repo;\n if (repoFullName === undefined) {\n repo = this.sourceRepo;\n } else {\n const [username, repoName] = repoFullName.split('/');\n repo = this.github.getRepo(username, repoName);\n }\n try {\n const response = await repo.getContents('master', '');\n\n return response.data.map((content) => content.path);\n } catch (e) {\n return [];\n }\n }\n\n async getDbcContents(dbcPath, repoFullName) {\n let repo;\n if (repoFullName === undefined) {\n repo = this.sourceRepo;\n } else {\n const [username, repoName] = repoFullName.split('/');\n repo = this.github.getRepo(username, repoName);\n }\n\n const fileContents = await repo.getContents('master', dbcPath);\n\n const rawContentsUrl = fileContents.data.download_url;\n\n const resp = await fetch(rawContentsUrl, { cache: 'no-cache' });\n\n return resp.text();\n }\n\n repoSourceIsOpenDbc(repoDetails) {\n return (\n repoDetails.source && repoDetails.source.full_name === OPENDBC_SOURCE_REPO\n );\n }\n\n async getUserOpenDbcFork() {\n const githubUsername = await this.getGithubUsername();\n if (!githubUsername) return null;\n\n const openDbcFork = this.github.getRepo(githubUsername, 'opendbc');\n const repoDetailResp = await openDbcFork.getDetails();\n const repoDetails = repoDetailResp.data;\n\n if (this.repoSourceIsOpenDbc(repoDetails)) {\n return repoDetails.full_name;\n }\n return null;\n }\n\n async fork() {\n const forkResponse = await this.sourceRepo.fork();\n if (forkResponse.status === 202) {\n return true;\n }\n return false;\n }\n\n async commitFile(repoFullName, path, contents, commitMessage) {\n /*\n repo is of format username/reponame\n authenciated user must have write access to repo\n */\n const [user, repoName] = repoFullName.split('/');\n const repo = this.github.getRepo(user, repoName);\n\n // get HEAD reference\n const refResp = await repo.getRef('heads/master');\n const ref = refResp.data;\n\n // get HEAD commit sha\n const headCommitResp = await repo.getCommit(ref.object.sha);\n const headCommit = headCommitResp.data;\n\n // get HEAD tree\n const headTreeResp = await repo.getTree(headCommit.tree.sha);\n const headTree = headTreeResp.data;\n\n // create new tree\n const tree = [\n {\n mode: '100644',\n path,\n type: 'blob',\n content: contents\n }\n ];\n\n const createTreeResp = await repo.createTree(tree, headTree.sha);\n const createdTree = createTreeResp.data;\n\n // commit\n const commitResp = await repo.commit(\n headCommit.sha,\n createdTree.sha,\n commitMessage || 'OpenDBC updates'\n );\n const commit = commitResp.data;\n\n // update HEAD\n const updateHeadResp = await repo.updateHead(\n 'heads/master',\n commit.sha,\n false\n );\n\n return updateHeadResp.status === 200;\n }\n}\n","export default class Frame {\n constructor({\n name,\n id = 0,\n size = 0,\n transmitters = [],\n extended = 0,\n comment = null,\n signals = {}\n }) {\n Object.assign(this, {\n name,\n id,\n size,\n transmitters,\n extended,\n comment,\n signals\n });\n }\n\n nextNewTransmitterName() {\n let txNum = 1;\n let txName;\n do {\n txName = `NEW_TRANSMITTER_${txNum}`;\n txNum++;\n } while (this.transmitters.indexOf(txName) !== -1);\n\n return txName;\n }\n\n addTransmitter() {\n const txName = this.nextNewTransmitterName();\n this.transmitters.push(txName);\n return txName;\n }\n\n header() {\n return (\n `BO_ ${this.id} ${this.name}: ${this.size} `\n + `${this.transmitters[0] || 'XXX'}`\n );\n }\n\n text() {\n const signals = Object.values(this.signals)\n .map((signal) => ` ${signal.text()}`) // indent\n .join('\\n');\n\n if (signals.length > 0) {\n return `${this.header()}\\n${signals}`;\n }\n return this.header();\n }\n\n copy() {\n const copy = Object.assign(Object.create(this), this);\n\n return copy;\n }\n}\n","import Moment from 'moment';\nimport CorollaDBC from './corolla-dbc';\n\nexport const demoLogUrls = [\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/0/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=8pT88IJhcarT3%2Bv0uaT3aoiMlOsPTru%2Bd%2B1mgCAUNzY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/1/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=RUiRh7VvDbhmGcam619Coz4FC0I%2B1M%2BgHzudTecU8N8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/2/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=vCx3vklGv09VY8Ox9Q8iinB7ZsrpDbsK4BMTkBt4biI%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/3/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=QtgjbhrpyoKHQC%2BIK/Ms0y%2BSh2EtHCAzBTV0BkPBbZ8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/4/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=xL6utQbOCRvdIV21Nq%2BsaxFzqDT4n212HwOSvdBC%2B%2Bg%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/5/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=9uxDaYILbAJRy2fAKYm9flHi237a2qTY8YlNfizTFSs%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/6/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=00Kno8VTcxQdazYL1lK0aVTt7zvnmWDwzbVJJQtXOfc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/7/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=eyTM64llEf6NrhoowAdqF76J7liL4ejq85HfKT7IoRU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/8/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=ashtAt8qucsBP8pBH24RYT4OrzHvBXA3SQPzTslWg10%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/9/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=C%2BvBxxhgscqUQr7dKF1t9wfhpy/16cl4lWsRfirblsM%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/10/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=4fcXFnGSe8TGQYP89H9Z4nEou2uANO3FPekTxUSP89Y%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/11/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=olfTiSNk49Y9tog4XfXHMSmDODNKQedaelfa9zhxyUI%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/12/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=Cea5FxaNoMzZUoPKfJKHSdEvZKgu130KbEYJ65HSHn4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/13/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=W/ycLCiCzfItDQeMDhkwAEl9FQ89UGDVipEIlAyL7fA%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/14/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=aXORJqBiOQda7tZPzwlD%2B4UJHhcWtKj5uoPqsmlTovI%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/15/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=C/OgqnPVkFhY11Ha5TiUkqr3bQyie5ZhIzWi73fxwog%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/16/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=gdzCLOnhMeNYJTE%2BXmuSlwYGVFIuxbsqHvygEKG0H8Q%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/17/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=6JZg3qh2sYdBQxRjA9GyjPv8eRgSsOakEjg0z9EDFZ0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/18/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=SYX7%2BN9npUSEdw2eVHngMAxXm5N5nwVos%2B32RpI675k%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/19/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=cOKcrLoyEUhfWOjIDr/edtvEchBsnEg3ma%2ByCOzf8GY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/20/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=yNMFoLourSvuG0Buor9fuPryheCkknxqvA0CoGVRfQ0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/21/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=f1AfgqSNOeOkthYxmV/bMnG6WaEnRBtrYMu6EaG133k%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/22/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=7PMH8rRci6jYaRHvnvqK24EO/bR06M72OtA0fpM7yiE%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/23/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=0UzWpng3TCr3DQ/dWi5vYLgsLL/yOw%2BQVWdtu3%2BnxH8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/24/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=vlFw7Che8rISI5gyKZoSif6nkN9vThi93cJpyPAJge8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/25/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=uVGejY1C9So%2B4Fc49Ihi5Fj5Tdyi4LofKYQE%2BYPTS5o%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/26/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=Uau%2BAbXw6JQglY/EUXsVj1hAx%2Bx7tS/dxpSij7DyEvQ%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/27/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=pzmqrxkVsy5XikPStD/5OPNrYWadB9qivHRU5nB1pCM%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/28/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=3dajisn7zt3MxhFKNxZgZn1PtUdege4Qh8d7AlCv6V4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/29/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=1NicoYGt%2BUFJbGYhGdTPnFCzYnIV5OHypuD3qzW53Wc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/30/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=1ZGt0PlbGaVeT/82JnG/qsuur04SGNlBbWAOcPvHvGU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/31/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=nDe5iODqha7NAugL0qe%2BnT7HKIqQNDS5vBcaxTHqwHY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/32/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=cBu8MgQvz9dvg7iydERnupmAyuYSas3wY3alT2wmQtQ%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/33/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=RMqrZgILMOZ/EOBwDw/SVTpjmQTFQz91RUQKCdzJYcE%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/34/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=srl6LGcWdQSlMMnuv%2B7aTFTMY4KpR9F%2BXo3XtMIeFSs%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/35/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=x109982KLJzI5CxYp0Txbgc6KWAk0FrP1TKasLbs4xY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/36/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=nEclbIDfZ6kPHJoOol/jXLd9dd5Dak5t4aDYdAc8NT0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/37/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=N4417uFhPrKwfkhPplH/PZvE7nHlPHyOUHUcXtV8ga8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/38/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=V35yVoPP3key5d8XJUk1Hs29RUD63qGDrqtsMTJJvq8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/39/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=qIQOoVL4qOWxXLPhUN/wlNnE0ubo/bcY8kSAeBUaYAY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/40/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=HfcEb0EtuMmzw579abyE8MdE%2BsTfszhXEB%2BRxUU3JH0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/41/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=CcY6L8NEIvMmrtxT46yAkTEV4bpj1022r/oXhaLNzZk%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/42/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=3xqT%2BO8YrFDv6C7U41ToVa5doDhuYKCzK5MxBcXt%2BWc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/43/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=FlIiq6qej5DOD5JnMPWKIbiX2/j8ysbIhBoR%2BtLspZg%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/44/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=2526%2Br0Ish0e9rkOeL3ub0/EfJhng%2BRYIev2PepghHk%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/45/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=vBrFpsNhNuzWhe8uncDkvObJUmeKMC1hQLySOUaex0I%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/46/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=zG6%2BxU3XWzipNxov0fkxEsUH4lyihThJpFjq4XlDnx4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/47/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=8Sw1doUy3u7V/mSkA1bFms54oBcKD8dpFm79vbxnhlY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/48/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=yfnYUwdcrK976YNJEg%2BMJlZbp99ewQjJgsR%2Bl8opCQI%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/49/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=hqEJFHSAekMOVYVlN5sCEgunR0e7M57eCrqB2IMtmKw%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/50/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=pL5GMwiT%2BD72Zk9EuMXwwFfWVF9jMWbTEU0HyCl6xNc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/51/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=gT08LFSoWUTdOGB2d%2BZtDWZQEvlsPkkNKra2T0WjLPU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/52/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=LtMWWoyfUPcFbf42%2BHR/n6iEnr/jocJSEt6LFdfqCKc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/53/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=4hBGTbNueUnHg951XoqyKAx2ZqxvlstfaY2cw9wTyUc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/54/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=p8wj4bI7u/uZOA58Te8U6T0%2BtDrYqeUkhInQuA5Rm94%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/55/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=1FLm5rAamUv8nEaaHjQ2s0SpLWbH5ZhCi8nOw5mfg9w%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/56/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=gcwoay0grLf%2BGAqrBeleuQxO77Hw/1N0pdofnnZB/64%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/57/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=GWFjquKtWJDtSi5op4oh4kV1VWekHkLu3VjO7j2ly/0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/58/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=hLIGYFB6u2l/eAzHeWL7EtM3G7LkzY2sUIJWBweRf8Y%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/59/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=ujjLQ5mblJBh2X%2BHn%2B%2BAbXBUkvU9l/6FKgkFIOqDUWw%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/60/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=9kSUr7Xn1tEanZ/JTjyJ2GZ9GdLKOk7Q0gj8rL6nhdU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/61/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=4lppdcyHqbjjcUJjHigd8id8n4KCwZZ/F8QJqgYPfcw%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/62/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=GhcxMBVVfDxeb0DnH%2BW745r1AK7/6mLIGrV33HTeUbQ%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/63/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=IwL9LtlEIW8kye3wBMSs1tXeJ2/QX3QiTv4NeO8OZcU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/64/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=EQDreY7wGnaCbpUbbVb%2BcIfBvp2oRaAVZjk00skP9vQ%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/65/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=PibH5ZpIvB2LPM/zSntil/CokrDpjC%2B5kfkC0/%2BYjbg%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/66/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=f4iKTgwmMErhnVt8MNGT6JSGqMu4D0Bl5kfn1P5m%2Bgs%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/67/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=uiLbcoMzZ6obysSHcHOzv9DphFInXl94YaYSGfI1CrY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/68/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=NzPA4KuadgoeY7hKvTKo1LXl47AEv0izaxgcU2Y1%2BN4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/69/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=aw%2BuDvwR/HYn7kZ/hHQ0%2Bkae1uOB/mX0aT618O49DvU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/70/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=15b6prxm0DzVlIEn93DCoxmnzr3FAl0R9C9FrSP8R8Y%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/71/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=sKviFsAarezfOAKkqFpbzpVuPsXhsWZmICzES2ivp/A%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/72/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=DRBRZf3KQX%2Bat%2BwMZaMR%2BpGJm%2BREVVe5kcjes4eYBiE%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/73/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=grzo4xrtUJvuJ9VtSx7Eg9rA/ffKzyYBDUYzykjGO8Y%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/74/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=9rf%2B%2BTL/yVd2cVoZNbkj3YClBLv77tGr1HRNii0rO2s%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/75/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=eB2k1u9DlDWb0e0JS4D6UPDtEdPx4RHimI%2BVzy1MhEM%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/76/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=355VfjSkCdkAOjqRMobPbG3GB1JMhFyvq/7dtGheRkM%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/77/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=ZfBc/b%2BWQGryLAEpwC0BtjHijtPghKP2b1b0bzCxehQ%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/78/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=hj6Patnin49Cb7R%2BMeyZGBte6vxHH62HUelOh2bcBbA%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/79/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=Nuk1gxAUd3s4WU7%2B320emlocY2Tie0eMsiEl6xUpSBA%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/80/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=iPZnh/bigsA9iyPjSTjzl5OIdzGfFgmH9IdFwA3mTRw%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/81/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=mKgB9AmAfv8%2BrPJ%2BLTaVA/eD1IYKaICeMwCgSn65jXs%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/82/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=QgmLKKEvf272qOywdLl3BRSogk7oAIeknRThsI%2BbLqY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/83/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=zBdCaBDmhg8aeWHMh3fMdQaXLJkSjaaq6waHoex4yJI%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/84/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=ddv/Q22WEJB1R%2B6bJWZD%2BB3IHKoEzJaYQmayYkHdrlU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/85/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=w3brrO7geBl/0n/jM7W7BZruQMNfM0SorGqiQeyJaBE%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/86/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=3Y2zucu35QtodXd1PDpYfJDK9i%2BY2LVpdjvVa8oYQt4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/87/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=n9ZsshnO5VEAAKVDOmn0AzhizE0y4Lb2iiszjt7Yous%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/88/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=snYOFNllT3jmKfwpiMPWpEV7tfS9RQCVSurDY98bIao%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/89/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=Xtwom5ycw0J57jrzDQPz6OhpWjsFi0nEfqVrkeQrl6A%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/90/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=US8vj1Db7jig7RRlYSnDAZK3UYH4gm42Af6UrzpbryA%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/91/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=nm8WvWPnc8zHKnoqA6NkqX1N93kIx9sPVmcJ5xJiteY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/92/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=wsg/P6/%2BKebsVfM/6lqTiwCsCvPJFQsPUunBOg0MScU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/93/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=H8eCBNN%2Btof3R3lvR6v41BZEjWcDXD7so8j0l03%2B99Y%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/94/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=HjU5sSYU5aeI/t9nCz4NkFiRdA0Tqtnx%2BLxinItdTo4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/95/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=NnunGZoAH/D0cq8n0sQHRlhZ1v1o5JwKk/1UfVAu92c%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/96/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=wCaqsHbtyNHcylPtP9FXxMwhl5YJ97trLhJtePtcLkY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/97/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=j1I%2BZ0CTlxrM956TgrPYrCFJx3D09qrNEGq8BNbqVJ0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/98/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=Gk9jF7lxFRq9nj3UTE0/YlDQBWYdL3ySUdl8gbj1UgE%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/99/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=DiZFcnCI1f47rHaVM9mY9YzZsZA8ToOBHuHgBHtqj9E%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/100/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=e0bEXWFLAeUeRYpFZ8LmBUJM7YKb5u5AyKOlMo7Klf8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/101/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=rpqSuP1Tu0JuR1ELug3T59We2o2wfwa2Xp2WIccz%2Bb8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/102/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=K3l/Hbbjaii3OK/A4nBtgjynG2A69gHnqnjHAwl01CY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/103/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=VtDMGUrEJKdn8he9B1WYnsuM8Zj4z6Nia7iu3oQNL5I%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/104/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=SxNgqjOUa3mx5aX3RIJQVApmd3L4JUP2megVGJ1XKjA%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/105/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=M/XvJE7X/dFSv6Iem%2BhkjIyJVFa22R9N79Xn8UnaCAI%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/106/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=cfreGuFOl0/TWe/fkZ5FEewkpRZXrVU8y94Fa582nb0%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/107/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=GWnZksWyn33Umz1l/c0ZjwkE9NYxdMqmiDRbBPVdlMc%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/108/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=AeUDO3Y/uhyGFvBO8tFpjQlJNoVzTXrxBL2v/eDIqvg%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/109/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=SG2Sy6ggdaW55GZbJwII2RS5REnrCXuw5znrhT%2BdkMQ%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/110/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=oX/xwJpbDDy4jOg%2B4/XIR/ezcN6u9r/6jIsF33OOUw8%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/111/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=2Wfq6bueVjYMfMQta3wjMKtJ3g4B1OF3GmQdzWK8S0M%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/112/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=psxUuVNKxDeu3g5xv3%2BuhdP7rrkP2cOcZ7FJNxRKCh4%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/113/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=1IySoCLFLTECiZHbcqQis4AfGrJRId3hL0Z3uz8VFiE%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/114/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=gwhHD0US%2BbJSdPWg8GWXMW96i3fNfucj2mzx21dTLAM%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/115/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=7IH32d3YfNF01b42I3yTKMtxPO2o9bgZm4Uj0iqYeJM%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/116/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=33QBRPx8hX667YX17JgAfyDz97do8cROISHR/jBw1YU%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/117/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=BhgFg6c74rMFYuxKYZfmgZH6YZGgPb9aEo7IHw5dXhY%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/118/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=TCxgujxDOtvGWsKpheHV0HH1MnbE3x6gSDsQs2Y5S1U%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/119/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=YO0I3SV5PBNpq5zn%2BxOvkfdz8YwHVcPMIovL1h%2BeS/o%3D\",\n \"https://commadata2.blob.core.windows.net/preserve/3533c53bb29502d1/2019-12-10--01-13-27/120/rlog.bz2?se=2025-01-10T18%3A54%3A24Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3Drlog.bz2&sig=aluzhD7EJgmN1mFZStJACXSLsfJL4vxNBr0RKLxPDWY%3D\"\n];\n\nexport const demoProps = {\n max: demoLogUrls.length,\n name: '2019-12-10--01-13-27',\n dongleId: '3533c53bb29502d1',\n dbc: CorollaDBC,\n isDemo: true,\n dbcFilename: 'toyota_nodsu_pt_generated.dbc',\n};\n\nexport const demoRoute = {\n fullname: '3533c53bb29502d1|2019-12-10--01-13-27',\n proclog: demoProps.max,\n start_time: Moment(demoProps.name, 'YYYY-MM-DD--H-m-s'),\n url: 'https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/3533c53bb29502d1/02505e68c591e4160b38210fa5f8d44a_2019-12-10--01-13-27'\n};\n\n","// Vendored from https://github.com/rapid7/le_js, which is broken with webpack.\n/* eslint-disable */\n\nif (typeof window === \"undefined\") {\n // eslint-disable-line no-use-before-define\n var window = self;\n}\nvar _indexOf = function(array, obj) {\n for (var i = 0; i < array.length; i++) {\n if (obj === array[i]) {\n return i;\n }\n }\n return -1;\n};\n\n// Obtain a browser-specific XHR object\nvar _getAjaxObject = function() {\n if (typeof XDomainRequest !== \"undefined\") {\n // We're using IE8/9\n return new XDomainRequest();\n }\n return new XMLHttpRequest();\n};\n\n/**\n * A single log event stream.\n * @constructor\n * @param {Object} options\n */\nfunction LogStream(options) {\n /**\n * @const\n * @type {string} */\n var _traceCode = options.trace\n ? (Math.random() + Math.PI).toString(36).substring(2, 10)\n : null;\n /** @type {string} */\n var _pageInfo = options.page_info;\n /** @type {string} */\n var _token = options.token;\n /** @type {boolean} */\n var _print = options.print;\n /** @type {boolean} */\n var _noFormat = options.no_format;\n /** @type {boolean} */\n var _SSL = (function() {\n if (typeof XDomainRequest === \"undefined\") {\n return options.ssl;\n }\n // If we're relying on XDomainRequest, we\n // must adhere to the page's encryption scheme.\n return window.location.protocol === \"https:\" ? true : false;\n })();\n /** @type {string} */\n var _endpoint;\n if (window.LEENDPOINT) {\n _endpoint = window.LEENDPOINT;\n } else if (_noFormat) {\n _endpoint = \"webhook.logentries.com/noformat\";\n } else {\n _endpoint = \"js.logentries.com/v1\";\n }\n _endpoint = (_SSL ? \"https://\" : \"http://\") + _endpoint + \"/logs/\" + _token;\n\n /**\n * Flag to prevent further invocations on network err\n ** @type {boolean} */\n var _shouldCall = true;\n /** @type {Array.<string>} */\n var _backlog = [];\n /** @type {boolean} */\n var _active = false;\n /** @type {boolean} */\n var _sentPageInfo = false;\n\n var _apiCall = function(token, data) {\n _active = true;\n\n var request = _getAjaxObject();\n\n if (_shouldCall) {\n if (request.constructor === XMLHttpRequest) {\n // Currently we don't support fine-grained error\n // handling in older versions of IE\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n // Handle any errors\n if (request.status >= 400) {\n console.error(\"Couldn't submit events.\");\n if (request.status === 410) {\n // This API version has been phased out\n console.warn(\"This version of le_js is no longer supported!\");\n }\n } else {\n if (request.status === 301) {\n // Server issued a deprecation warning\n console.warn(\n \"This version of le_js is deprecated! Consider upgrading.\"\n );\n }\n if (_backlog.length > 0) {\n // Submit the next event in the backlog\n _apiCall(token, _backlog.shift());\n } else {\n _active = false;\n }\n }\n }\n };\n } else {\n request.onload = function() {\n if (_backlog.length > 0) {\n // Submit the next event in the backlog\n _apiCall(token, _backlog.shift());\n } else {\n _active = false;\n }\n };\n }\n\n request.open(\"POST\", _endpoint, true);\n if (request.constructor === XMLHttpRequest) {\n request.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n request.setRequestHeader(\"Content-type\", \"application/json\");\n }\n\n if (request.overrideMimeType) {\n request.overrideMimeType(\"text\");\n }\n\n request.send(data);\n }\n };\n\n var _getEvent = function() {\n var raw = null;\n var args = Array.prototype.slice.call(arguments);\n if (args.length === 0) {\n throw new Error(\"No arguments!\");\n } else if (args.length === 1) {\n raw = args[0];\n } else {\n // Handle a variadic overload,\n // e.g. _rawLog(\"some text \", x, \" ...\", 1);\n raw = args;\n }\n return raw;\n };\n\n var _agentInfo = function() {\n var nav = window.navigator || { doNotTrack: undefined };\n var screen = window.screen || {};\n var location = window.location || {};\n\n return {\n url: location.pathname,\n referrer: document.referrer,\n screen: {\n width: screen.width,\n height: screen.height\n },\n window: {\n width: window.innerWidth,\n height: window.innerHeight\n },\n browser: {\n name: nav.appName,\n version: nav.appVersion,\n cookie_enabled: nav.cookieEnabled,\n do_not_track: nav.doNotTrack\n },\n platform: nav.platform\n };\n };\n\n // Single arg stops the compiler arity warning\n var _rawLog = function(msg) {\n var event = _getEvent.apply(this, arguments);\n\n var data = { event: event };\n\n // Add agent info if required\n if (_pageInfo !== \"never\") {\n if (!_sentPageInfo || _pageInfo === \"per-entry\") {\n _sentPageInfo = true;\n if (\n typeof event.screen === \"undefined\" &&\n typeof event.browser === \"undefined\"\n )\n _rawLog(_agentInfo())\n .level(\"PAGE\")\n .send();\n }\n }\n\n if (_traceCode) {\n data.trace = _traceCode;\n }\n\n return {\n level: function(l) {\n // Don't log PAGE events to console\n // PAGE events are generated for the agentInfo function\n if (_print && typeof console !== \"undefined\" && l !== \"PAGE\") {\n var serialized = null;\n if (typeof XDomainRequest !== \"undefined\") {\n // We're using IE8/9\n serialized = data.trace + \" \" + data.event;\n }\n try {\n console[l.toLowerCase()].call(console, serialized || data);\n } catch (ex) {\n // IE compat fix\n console.log(serialized || data);\n }\n }\n data.level = l;\n\n return {\n send: function() {\n var cache = [];\n var serialized = JSON.stringify(data, function(key, value) {\n if (typeof value === \"undefined\") {\n return \"undefined\";\n } else if (typeof value === \"object\" && value !== null) {\n if (_indexOf(cache, value) !== -1) {\n // We've seen this object before;\n // return a placeholder instead to prevent\n // cycles\n return \"<?>\";\n }\n cache.push(value);\n }\n return value;\n });\n\n if (_active) {\n _backlog.push(serialized);\n } else {\n _apiCall(_token, serialized);\n }\n }\n };\n }\n };\n };\n\n if (options.catchall) {\n var oldHandler = window.onerror;\n var newHandler = function(msg, url, line) {\n _rawLog({ error: msg, line: line, location: url })\n .level(\"ERROR\")\n .send();\n if (oldHandler) {\n return oldHandler(msg, url, line);\n } else {\n return false;\n }\n };\n window.onerror = newHandler;\n }\n\n /** @expose */\n this.log = _rawLog;\n}\n\n/**\n * A single log object\n * @constructor\n * @param {Object} options\n */\nfunction Logger(options) {\n var logger;\n\n // Default values\n var dict = {\n ssl: true,\n catchall: false,\n trace: true,\n page_info: \"never\",\n print: false,\n endpoint: null,\n token: null\n };\n\n if (typeof options === \"object\") for (var k in options) dict[k] = options[k];\n else throw new Error(\"Invalid parameters for createLogStream()\");\n\n if (dict.token === null) {\n throw new Error(\"Token not present.\");\n } else {\n logger = new LogStream(dict);\n }\n\n var _log = function(msg) {\n if (logger) {\n return logger.log.apply(this, arguments);\n } else throw new Error(\"You must call LE.init(...) first.\");\n };\n\n // The public interface\n return {\n log: function() {\n _log\n .apply(this, arguments)\n .level(\"LOG\")\n .send();\n },\n warn: function() {\n _log\n .apply(this, arguments)\n .level(\"WARN\")\n .send();\n },\n error: function() {\n _log\n .apply(this, arguments)\n .level(\"ERROR\")\n .send();\n },\n info: function() {\n _log\n .apply(this, arguments)\n .level(\"INFO\")\n .send();\n }\n };\n}\n\n// Array of Logger elements\nvar loggers = {};\n\nvar _getLogger = function(name) {\n if (!loggers.hasOwnProperty(name))\n throw new Error(\"Invalid name for logStream\");\n\n return loggers[name];\n};\n\nvar _createLogStream = function(options) {\n if (typeof options.name !== \"string\") throw new Error(\"Name not present.\");\n else if (loggers.hasOwnProperty(options.name))\n throw new Error(\"A logger with that name already exists!\");\n loggers[options.name] = new Logger(options);\n\n return true;\n};\n\nvar _deprecatedInit = function(options) {\n var dict = {\n name: \"default\"\n };\n\n if (typeof options === \"object\") for (var k in options) dict[k] = options[k];\n else if (typeof options === \"string\") dict.token = options;\n else throw new Error(\"Invalid parameters for init()\");\n\n return _createLogStream(dict);\n};\n\nvar _destroyLogStream = function(name) {\n if (typeof name === \"undefined\") {\n name = \"default\";\n }\n\n delete loggers[name];\n};\n\n// The public interface\nexport default {\n init: _deprecatedInit,\n createLogStream: _createLogStream,\n to: _getLogger,\n destroy: _destroyLogStream,\n log: function() {\n for (var k in loggers) loggers[k].log.apply(this, arguments);\n },\n warn: function() {\n for (var k in loggers) loggers[k].warn.apply(this, arguments);\n },\n error: function() {\n for (var k in loggers) loggers[k].error.apply(this, arguments);\n },\n info: function() {\n for (var k in loggers) loggers[k].info.apply(this, arguments);\n }\n};\n","import DBC from './models/can/dbc';\n\nconst CorollaDBC = new DBC(`\nCM_ \"AUTOGENERATED FILE, DO NOT EDIT\"\n\n\nCM_ \"Imported file _comma.dbc starts here\"\nBO_ 359 STEERING_IPAS_COMMA: 8 IPAS\n SG_ STATE : 7|4@0+ (1,0) [0|15] \"\" XXX\n SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] \"deg\" XXX\n SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] \"\" XXX\n SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] \"\" XXX\n SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SET_ME_X00 : 55|8@0+ (1,0) [0|255] \"\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nCM BO_ STEERING_IPAS_COMMA \"Copy of msg 614 so we can do angle control while the Park Assist ECU is connected (Panda spoofs 614 with 359 on connector J70). Note that addresses 0x266 and 0x167 are checksum-invariant\";\n\n BO_ 512 GAS_COMMAND: 6 EON\n SG_ GAS_COMMAND : 7|16@0+ (0.159375,-75.555) [0|1] \"\" INTERCEPTOR\n SG_ GAS_COMMAND2 : 23|16@0+ (0.159375,-151.111) [0|1] \"\" INTERCEPTOR\n SG_ ENABLE : 39|1@0+ (1,0) [0|1] \"\" INTERCEPTOR\n SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] \"\" INTERCEPTOR\n SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] \"\" INTERCEPTOR\n\n BO_ 513 GAS_SENSOR: 6 INTERCEPTOR\n SG_ INTERCEPTOR_GAS : 7|16@0+ (0.159375,-75.555) [0|1] \"\" EON\n SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.159375,-151.111) [0|1] \"\" EON\n SG_ STATE : 39|4@0+ (1,0) [0|15] \"\" EON\n SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] \"\" EON\n SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] \"\" EON\n\n VAL_ 513 STATE 5 \"FAULT_TIMEOUT\" 4 \"FAULT_STARTUP\" 3 \"FAULT_SCE\" 2 \"FAULT_SEND\" 1 \"FAULT_BAD_CHECKSUM\" 0 \"NO_FAULT\" ;\n\n\nCM_ \"Imported file _toyota_2017.dbc starts here\"\nVERSION \"\"\n\n\nNS_ :\n NS_DESC_\n CM_\n BA_DEF_\n BA_\n VAL_\n CAT_DEF_\n CAT_\n FILTER\n BA_DEF_DEF_\n EV_DATA_\n ENVVAR_DATA_\n SGTYPE_\n SGTYPE_VAL_\n BA_DEF_SGTYPE_\n BA_SGTYPE_\n SIG_TYPE_REF_\n VAL_TABLE_\n SIG_GROUP_\n SIG_VALTYPE_\n SIGTYPE_VALTYPE_\n BO_TX_BU_\n BA_DEF_REL_\n BA_REL_\n BA_DEF_DEF_REL_\n BU_SG_REL_\n BU_EV_REL_\n BU_BO_REL_\n SG_MUL_VAL_\n\nBS_:\n\nBU_: XXX DSU HCU EPS IPAS CGW\n\nBO_ 36 KINEMATICS: 8 XXX\n SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] \"m/s^2\" XXX\n SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] \"deg/sec\" XXX\n SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] \"\" XXX\n\nBO_ 37 STEER_ANGLE_SENSOR: 8 XXX\n SG_ STEER_ANGLE : 3|12@0- (1.5,0) [-500|500] \"deg\" XXX\n SG_ STEER_FRACTION : 39|4@0- (0.1,0) [-0.7|0.7] \"deg\" XXX\n SG_ STEER_RATE : 35|12@0- (1,0) [-2000|2000] \"deg/s\" XXX\n\nBO_ 166 BRAKE: 8 XXX\n SG_ BRAKE_AMOUNT : 7|8@0+ (1,0) [0|255] \"\" XXX\n SG_ BRAKE_PEDAL : 23|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 170 WHEEL_SPEEDS: 8 XXX\n SG_ WHEEL_SPEED_FR : 7|16@0+ (0.01,-67.67) [0|250] \"kph\" XXX\n SG_ WHEEL_SPEED_FL : 23|16@0+ (0.01,-67.67) [0|250] \"kph\" XXX\n SG_ WHEEL_SPEED_RR : 39|16@0+ (0.01,-67.67) [0|250] \"kph\" XXX\n SG_ WHEEL_SPEED_RL : 55|16@0+ (0.01,-67.67) [0|250] \"kph\" XXX\n\nBO_ 180 SPEED: 8 XXX\n SG_ ENCODER : 39|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SPEED : 47|16@0+ (0.01,0) [0|250] \"kph\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 353 DSU_SPEED: 8 XXX\n SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] \"kph\" XXX\n\nBO_ 466 PCM_CRUISE: 8 XXX\n SG_ GAS_RELEASED : 4|1@0+ (1,0) [0|1] \"\" XXX\n SG_ CRUISE_ACTIVE : 5|1@0+ (1,0) [0|1] \"\" XXX\n SG_ STANDSTILL_ON : 12|1@0+ (1,0) [0|1] \"\" XXX\n SG_ ACCEL_NET : 23|16@0- (0.001,0) [-20|20] \"m/s2\" XXX\n SG_ CRUISE_STATE : 55|4@0+ (1,0) [0|15] \"\" XXX\n SG_ CANCEL_REQ : 49|1@1+ (1,0) [0|1] \"\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 467 PCM_CRUISE_2: 8 XXX\n SG_ MAIN_ON : 15|1@0+ (1,0) [0|1] \"\" XXX\n SG_ LOW_SPEED_LOCKOUT : 14|2@0+ (1,0) [0|3] \"kph\" XXX\n SG_ SET_SPEED : 23|8@0+ (1,0) [0|255] \"kph\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 552 ACCELEROMETER: 8 XXX\n SG_ ACCEL_Z : 22|15@0- (1,0) [0|32767] \"\" XXX\n SG_ ACCEL_X : 6|15@0- (0.001,0) [-20|20] \"m/s2\" XXX\n\nBO_ 560 BRAKE_MODULE2: 7 XXX\n SG_ BRAKE_PRESSED : 26|1@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 614 STEERING_IPAS: 8 IPAS\n SG_ STATE : 7|4@0+ (1,0) [0|15] \"\" XXX\n SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] \"deg\" XXX\n SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] \"\" XXX\n SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] \"\" XXX\n SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SET_ME_X00_1 : 55|8@0+ (1,0) [0|255] \"\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 643 PRE_COLLISION: 7 DSU\n SG_ COUNTER : 7|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SET_ME_X00 : 15|8@0+ (1,0) [0|255] \"\" XXX\n SG_ FORCE : 23|16@0- (2,0) [0|255] \"N\" XXX\n SG_ SET_ME_X002 : 33|8@0+ (1,0) [0|3] \"\" XXX\n SG_ BRAKE_STATUS : 39|3@0+ (1,0) [0|255] \"\" XXX\n SG_ STATE : 36|3@0+ (1,0) [0|255] \"\" XXX\n SG_ SET_ME_X003 : 40|1@0+ (1,0) [0|1] \"\" XXX\n SG_ PRECOLLISION_ACTIVE : 41|1@0+ (1,0) [0|255] \"\" XXX\n SG_ CHECKSUM : 55|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 740 STEERING_LKA: 5 XXX\n SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] \"\" XXX\n SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] \"\" XXX\n SG_ COUNTER : 6|6@0+ (1,0) [0|63] \"\" XXX\n SG_ SET_ME_1 : 7|1@0+ (1,0) [0|1] \"\" XXX\n SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] \"\" XXX\n SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 742 LEAD_INFO: 8 DSU\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" HCU\n SG_ LEAD_REL_SPEED : 23|12@0- (0.025,0) [-100|100] \"m/s\" HCU\n SG_ LEAD_LONG_DIST : 7|13@0+ (0.05,0) [0|300] \"m\" HCU\n\nBO_ 835 ACC_CONTROL: 8 DSU\n SG_ ACCEL_CMD : 7|16@0- (0.001,0) [-20|20] \"m/s2\" HCU\n SG_ SET_ME_X01 : 23|2@0+ (1,0) [0|3] \"\" HCU\n SG_ DISTANCE : 20|1@0+ (1,0) [0|1] \"\" XXX\n SG_ MINI_CAR : 21|1@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X3 : 19|4@0+ (1,0) [0|15] \"\" XXX\n SG_ SET_ME_1 : 30|1@0+ (1,0) [0|1] \"\" HCU\n SG_ RELEASE_STANDSTILL : 31|1@0+ (1,0) [0|1] \"\" HCU\n SG_ CANCEL_REQ : 24|1@0+ (1,0) [0|1] \"\" HCU\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 836 PRE_COLLISION_2: 8 DSU\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 869 DSU_CRUISE : 7 DSU\n SG_ RES_BTN : 3|1@0+ (1,0) [0|0] \"\" XXX\n SG_ SET_BTN : 2|1@0+ (1,0) [0|0] \"\" XXX\n SG_ CANCEL_BTN : 1|1@0+ (1,0) [0|0] \"\" XXX\n SG_ MAIN_ON : 0|1@0+ (1,0) [0|0] \"\" XXX\n SG_ SET_SPEED : 15|8@0+ (1,0) [0|0] \"km/h\" XXX\n SG_ CRUISE_REQUEST : 31|8@0+ (100,-12800) [0|0] \"N\" XXX\n SG_ LEAD_DISTANCE : 39|8@0+ (1,0) [0|0] \"m\" XXX\n\nBO_ 921 PCM_CRUISE_SM: 8 XXX\n SG_ MAIN_ON : 4|1@0+ (1,0) [0|1] \"\" XXX\n SG_ CRUISE_CONTROL_STATE : 11|4@0+ (1,0) [0|15] \"\" XXX\n SG_ DISTANCE_LINES : 14|2@0+ (1,0) [0|3] \"\" XXX\n SG_ UI_SET_SPEED : 31|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 951 ESP_CONTROL: 8 ESP\n SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] \"\" XXX\n SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] \"\" XXX\n SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 1041 ACC_HUD: 8 DSU\n SG_ FCW : 4|1@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 1042 LKAS_HUD: 8 XXX\n SG_ BARRIERS : 1|2@0+ (1,0) [0|3] \"\" XXX\n SG_ RIGHT_LINE : 3|2@0+ (1,0) [0|3] \"\" XXX\n SG_ LEFT_LINE : 5|2@0+ (1,0) [0|3] \"\" XXX\n SG_ SET_ME_X01 : 7|2@0+ (1,0) [0|3] \"\" XXX\n SG_ SET_ME_X01_2 : 11|2@0+ (1,0) [0|3] \"\" XXX\n SG_ LDA_ALERT : 9|2@0+ (1,0) [0|3] \"\" XXX\n SG_ TWO_BEEPS : 12|1@0+ (1,0) [0|1] \"\" XXX\n SG_ ADJUSTING_CAMERA : 13|1@0+ (1,0) [0|1] \"\" XXX\n SG_ LDA_MALFUNCTION : 15|1@0+ (1,0) [0|1] \"\" XXX\n SG_ REPEATED_BEEPS : 32|1@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X0C : 23|8@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X2C : 47|8@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] \"\" XXX\n SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 1043 TIME : 8 CGW\n SG_ YEAR : 7|8@0+ (1,0) [0|0] \"year\" XXX\n SG_ MONTH : 15|8@0+ (1,0) [0|0] \"month\" XXX\n SG_ DAY : 23|8@0+ (1,0) [0|0] \"day\" XXX\n SG_ HOUR : 31|8@0+ (1,0) [0|0] \"hour\" XXX\n SG_ MINUTE : 39|8@0+ (1,0) [0|0] \"minute\" XXX\n SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] \"\" XXX\n SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] \"hours\" XXX\n SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] \"minutes\" XXX\n SG_ SUMMER : 60|1@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 1408 VIN_PART_1: 8 CGW\n SG_ VIN_1 : 7|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_2 : 15|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_3 : 23|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_4 : 31|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_5 : 39|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_6 : 47|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_7 : 55|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_8 : 63|8@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 1409 VIN_PART_2: 8 CGW\n SG_ VIN_9 : 7|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_10 : 15|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_11 : 23|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_12 : 31|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_13 : 39|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_14 : 47|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_15 : 55|8@0+ (1,0) [0|0] \"\" XXX\n SG_ VIN_16 : 63|8@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 1410 VIN_PART_3: 8 CGW\n SG_ VIN_17 : 7|8@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 1553 UI_SETTING: 8 XXX\n SG_ UNITS : 26|2@0+ (1,0) [0|3] \"\" XXX\n\nBO_ 1556 STEERING_LEVERS: 8 XXX\n SG_ TURN_SIGNALS : 29|2@0+ (1,0) [0|3] \"\" XXX\n\nBO_ 1568 SEATS_DOORS: 8 XXX\n SG_ SEATBELT_DRIVER_UNLATCHED : 62|1@0+ (1,0) [0|1] \"\" XXX\n SG_ DOOR_OPEN_FL : 45|1@0+ (1,0) [0|1] \"\" XXX\n SG_ DOOR_OPEN_RL : 42|1@0+ (1,0) [0|1] \"\" XXX\n SG_ DOOR_OPEN_RR : 43|1@0+ (1,0) [0|1] \"\" XXX\n SG_ DOOR_OPEN_FR : 44|1@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 1570 LIGHT_STALK: 8 SCM\n SG_ AUTO_HIGH_BEAM : 37|1@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 1161 RSA1: 8 FCM\n SG_ TSGN1 : 7|8@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNGRY1 : 12|3@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNHLT1 : 9|2@0+ (1,0) [0|0] \"\" XXX\n SG_ SPDVAL1 : 23|8@0+ (1,0) [0|0] \"kph\" XXX\n SG_ SPLSGN1 : 31|4@0+ (1,0) [0|0] \"\" XXX\n SG_ SPLSGN2 : 27|4@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGN2 : 39|8@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNGRY2 : 44|3@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNHLT2 : 41|2@0+ (1,0) [0|0] \"\" XXX\n SG_ SPDVAL2 : 55|8@0+ (1,0) [0|0] \"\" XXX\n SG_ BZRRQ_P : 63|2@0+ (1,0) [0|0] \"\" XXX\n SG_ BZRRQ_A : 61|2@0+ (1,0) [0|0] \"\" XXX\n SG_ SYNCID1 : 59|4@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 1162 RSA2: 8 FCM\n SG_ TSGN3 : 7|8@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNGRY3 : 12|3@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNHLT3 : 9|2@0+ (1,0) [0|0] \"\" XXX\n SG_ SPLSGN3 : 31|4@0+ (1,0) [0|0] \"\" XXX\n SG_ SPLSGN4 : 27|4@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGN4 : 39|8@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNGRY4 : 44|3@0+ (1,0) [0|0] \"\" XXX\n SG_ TSGNHLT4 : 41|2@0+ (1,0) [0|0] \"\" XXX\n SG_ DPSGNREQ : 54|1@0+ (1,0) [0|0] \"\" XXX\n SG_ SGNNUMP : 53|3@0+ (1,0) [0|0] \"\" XXX\n SG_ SGNNUMA : 50|3@0+ (1,0) [0|0] \"\" XXX\n SG_ SPDUNT : 63|2@0+ (1,0) [0|0] \"\" XXX\n SG_ TSRWMSG : 61|2@0+ (1,0) [0|0] \"\" XXX\n SG_ SYNCID2 : 59|4@0+ (1,0) [0|0] \"\" XXX\n\nBO_ 1163 RSA3: 8 FCM\n SG_ TSREQPD : 7|1@0+ (1,0) [0|0] \"\" XXX\n SG_ TSRMSW : 6|1@0+ (1,0) [0|0] \"\" XXX\n SG_ OTSGNNTM : 5|2@0+ (1,0) [0|0] \"\" XXX\n SG_ NTLVLSPD : 3|2@0+ (1,0) [0|0] \"\" XXX\n SG_ OVSPNTM : 1|2@0+ (1,0) [0|0] \"\" XXX\n SG_ OVSPVALL : 11|4@0+ (1,-5) [0|0] \"\" XXX\n SG_ OVSPVALM : 19|4@0+ (1,-5) [0|0] \"\" XXX\n SG_ OVSPVALH : 27|4@0+ (1,-5) [0|0] \"\" XXX\n SG_ TSRSPU : 33|2@0+ (1,0) [0|0] \"\" XXX\n\nCM_ SG_ 36 ACCEL_Y \"unit is tbd\";\nCM_ SG_ 36 YAW_RATE \"verify\";\nCM_ SG_ 36 STEERING_TORQUE \"does not seem the steer torque, tbd\";\nCM_ SG_ 37 STEER_FRACTION \"1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set\";\nCM_ SG_ 37 STEER_RATE \"factor is tbd\";\nCM_ SG_ 466 ACCEL_NET \"net acceleration produced by the system, given ACCEL_CMD, road grade and other factors\";\nCM_ SG_ 467 SET_SPEED \"43 kph are shown as 28mph, so conversion isnt perfect\";\nCM_ SG_ 467 LOW_SPEED_LOCKOUT \"in low speed lockout, system would always disengage below 28mph\";\nCM_ SG_ 560 BRAKE_PRESSED \"another brake pressed?\";\nCM_ SG_ 608 STEER_TORQUE_DRIVER \"driver torque\";\nCM_ SG_ 608 STEER_OVERRIDE \"set when driver torque exceeds a certain value\";\nCM_ SG_ 614 ANGLE \"set to measured angle when ipas control isn't active\";\nCM_ SG_ 643 COUNTER \"only used on cars that use this msg for cruise control\";\nCM_ SG_ 643 BRAKE_STATUS \"only used on cars that use this msg for cruise control\";\nCM_ SG_ 643 PRECOLLISION_ACTIVE \"set 0.5s before any braking\";\nCM_ SG_ 921 UI_SET_SPEED \"set speed shown in UI with user set unit\";\nCM_ SG_ 951 BRAKE_LIGHTS_ACC \"brake lights when ACC commands decel\";\nCM_ SG_ 1042 SET_ME_1 \"unclear what this is, but it's always 1 in drive traces\";\nCM_ SG_ 1042 REPEATED_BEEPS \"recommended for fcw and other important alerts\";\nCM_ SG_ 1161 SPDVAL1 \"Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.\";\nCM_ SG_ 1161 SYNCID1 \"counter from 1 to f at 1 Hz\";\nCM_ SG_ 1161 SPDVAL2 \"conditional speed value 70\"\nCM_ SG_ 1162 SGNNUMP \"1 if SPDVAL1 is set, otherwise 0\";\nCM_ SG_ 1162 SYNCID2 \"counter from 1 to f at 1 Hz\";\nCM_ SG_ 1163 TSREQPD \"always 1\";\nCM_ SG_ 1163 TSRMSW \"always 1\";\nCM_ SG_ 1163 OTSGNNTM \"always 3\";\nCM_ SG_ 1163 NTLVLSPD \"always 3\";\nCM_ SG_ 1163 OVSPNTM \"always 3\";\nCM_ SG_ 1163 OVSPVALL \"-5 at start then 2 after 2 seconds\";\nCM_ SG_ 1163 OVSPVALM \"-5 at start then 5 after 2 seconds\";\nCM_ SG_ 1163 OVSPVALH \"-5 at start then 10 after 2 seconds\";\nCM_ SG_ 1163 TSRSPU \"always 1\";\n\nVAL_ 466 CRUISE_STATE 8 \"active\" 7 \"standstill\" 1 \"off\";\nVAL_ 467 LOW_SPEED_LOCKOUT 2 \"low speed locked\" 1 \"ok\";\nVAL_ 614 STATE 3 \"enabled\" 1 \"disabled\";\nVAL_ 614 DIRECTION_CMD 3 \"right\" 2 \"center\" 1 \"left\";\nVAL_ 643 STATE 0 \"normal\" 1 \"adaptive_cruise_control\" 3 \"emergency_braking\";\nVAL_ 921 CRUISE_CONTROL_STATE 2 \"disabled\" 11 \"hold\" 10 \"hold_waiting_user_cmd\" 6 \"enabled\" 5 \"faulted\";\nVAL_ 1042 LDA_ALERT 3 \"hold with continuous beep\" 2 \"LDA unavailable\" 1 \"hold\" 0 \"none\";\nVAL_ 1042 BARRIERS 3 \"both\" 2 \"right\" 1 \"left\" 0 \"none\";\nVAL_ 1042 RIGHT_LINE 3 \"orange\" 2 \"faded\" 1 \"solid\" 0 \"none\";\nVAL_ 1042 LEFT_LINE 3 \"orange\" 2 \"faded\" 1 \"solid\" 0 \"none\";\nVAL_ 1553 UNITS 1 \"km\" 2 \"miles\";\nVAL_ 1556 TURN_SIGNALS 3 \"none\" 2 \"right\" 1 \"left\";\nVAL_ 1161 TSGN1 1 \"speed sign\" 0 \"none\";\nVAL_ 1161 TSGN2 1 \"speed sign\" 0 \"none\";\nVAL_ 1161 SPLSGN2 15 \"conditional blank\" 4 \"wet road\" 5 \"rain\" 0 \"none\";\nVAL_ 1162 TSGN3 0 \"none\" 1 \"speed sign\" 2 \"0 unlimited\" 7 \"unlimited\" 16 \"highway\" 17 \"no highway\" 18 \"motorway\" 19 \"no motorway\" 20 \"in city\" 21 \"outside city\" 22 \"pedestrian area\" 23 \"no pedestrian area\" 65 \"no overtaking left\" 66 \"no overtaking right\" 67 \"overtaking allowed again\" 129 \"no entry\";\nVAL_ 1162 SPLSGN3 15 \"conditional blank\" 4 \"wet road\" 5 \"rain\" 0 \"none\";\n\n\nCM_ \"CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180\";\n\nCM_ \"toyota_nodsu_pt.dbc starts here\"\n\n\n\nBO_ 401 STEERING_LTA: 8 XXX\n SG_ COUNTER : 7|8@0+ (1,0) [0|255] \"\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SETME_X3 : 29|2@0+ (1,0) [0|3] \"\" XXX\n SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] \"\" XXX\n SG_ SETME_X64 : 47|8@0+ (1,0) [0|255] \"\" XXX\n SG_ ANGLE : 55|8@0- (0.5,0) [0|255] \"\" XXX\n SG_ STEER_ANGLE_CMD : 15|16@0- (0.0573,0) [-540|540] \"\" XXX\n SG_ STEER_REQUEST : 25|1@0+ (1,0) [0|1] \"\" XXX\n SG_ BIT : 30|1@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 550 BRAKE_MODULE: 8 XXX\n SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] \"\" XXX\n SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|511] \"\" XXX\n SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|1] \"\" XXX\n\nBO_ 705 GAS_PEDAL: 8 XXX\n SG_ GAS_RELEASED : 3|1@0+ (1,0) [0|1] \"\" XXX\n SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] \"\" XXX\n\nBO_ 608 STEER_TORQUE_SENSOR: 8 XXX\n SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] \"\" XXX\n SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] \"\" XXX\n SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] \"\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] \"\" XXX\n\nBO_ 610 EPS_STATUS: 8 EPS\n SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] \"\" XXX\n SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] \"\" XXX\n SG_ TYPE : 24|1@0+ (1,0) [0|1] \"\" XXX\n SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] \"\" XXX\n\nBO_ 956 GEAR_PACKET: 8 XXX\n SG_ SPORT_ON : 2|1@0+ (1,0) [0|1] \"\" XXX\n SG_ GEAR : 13|6@0+ (1,0) [0|63] \"\" XXX\n SG_ ECON_ON : 40|1@0+ (1,0) [0|1] \"\" XXX\n\nCM_ SG_ 548 BRAKE_PRESSURE \"seems prop to pedal force\";\nCM_ SG_ 548 BRAKE_POSITION \"seems proportional to pedal displacement, unclear the max value of 0x1c8\";\nCM_ SG_ 610 TYPE \"seems 1 on Corolla, 0 on all others\";\nVAL_ 610 IPAS_STATE 5 \"override\" 3 \"enabled\" 1 \"disabled\";\nVAL_ 610 LKA_STATE 25 \"temporary_fault\" 9 \"temporary_fault2\" 5 \"active\" 1 \"standby\";\nVAL_ 956 GEAR 0 \"D\" 1 \"S\" 8 \"N\" 16 \"R\" 32 \"P\";\nVAL_ 956 SPORT_ON 0 \"off\" 1 \"on\";\nVAL_ 956 ECON_ON 0 \"off\" 1 \"on\";\n`);\n\nexport default CorollaDBC;\n","import Frame from './frame';\nimport Signal from './signal';\n\nexport const wheelSpeeds = {\n FrontLeftWheel: shortSignal({\n index: 0,\n factor: 0.001\n }),\n FrontRightWheel: shortSignal({\n index: 1,\n factor: 0.001\n }),\n RearLeftWheel: shortSignal({\n index: 2,\n factor: 0.001\n }),\n RearRightWheel: shortSignal({\n index: 3,\n factor: 0.001\n })\n};\n\nexport const ego = {\n VEgo: shortSignal({\n index: 0,\n factor: 0.001\n }),\n AEgo: shortSignal({\n index: 1,\n factor: 0.001\n }),\n VEgoRaw: shortSignal({\n index: 2,\n factor: 0.001\n }),\n YawRate: shortSignal({\n index: 3,\n factor: 0.001\n })\n};\n\nexport const controls = {\n SteeringAngle: longSignal({\n index: 0,\n factor: 0.001\n }),\n Brake: shortSignal({\n index: 2,\n factor: 0.001\n }),\n Gas: shortSignal({\n index: 3,\n factor: 0.001\n })\n};\n\nexport const flags = {\n LeftBlinker: boolSignal({\n index: 0\n }),\n RightBlinker: boolSignal({\n index: 1\n }),\n GenericToggle: boolSignal({\n index: 2\n }),\n DoorOpen: boolSignal({\n index: 3\n }),\n SeatbeltUnlatched: boolSignal({\n index: 4\n }),\n GasPressed: boolSignal({\n index: 5\n }),\n BrakeLights: boolSignal({\n index: 6\n }),\n SteeringPressed: boolSignal({\n index: 7\n }),\n Standstill: boolSignal({\n index: 8\n }),\n 'CruiseState.Enabled': boolSignal({\n index: 9\n }),\n 'CruiseState.Available': boolSignal({\n index: 10\n }),\n 'CruiseState.Standstill': boolSignal({\n index: 11\n }),\n GearShifter: {\n startBit: 15,\n size: 4,\n unsigned: true\n },\n 'CruiseState.Speed': charSignal({\n index: 2\n })\n};\n\nexport const ubloxGnss = {\n RcvTow: longSignal({\n index: 0\n }),\n GpsWeek: shortSignal({\n index: 2\n }),\n LeapSeconds: {\n startBit: 55,\n size: 8\n },\n NumMeas: {\n startBit: 63,\n size: 8\n }\n};\n\nexport const health = {\n Voltage: shortSignal({\n index: 0\n }),\n Current: charSignal({\n index: 2\n }),\n Started: boolSignal({\n index: 24\n }),\n ControlsAllowed: boolSignal({\n index: 25\n }),\n GasInterceptorDetected: boolSignal({\n index: 26\n }),\n StartedSignalDetected: boolSignal({\n index: 27\n })\n};\n\nexport const thermalCPU = {\n Cpu0: shortSignal({\n index: 0,\n unsigned: true\n }),\n Cpu1: shortSignal({\n index: 1,\n unsigned: true\n }),\n Cpu2: shortSignal({\n index: 2,\n unsigned: true\n }),\n Cpu3: shortSignal({\n index: 3,\n unsigned: true\n })\n};\n\nexport const thermalData = {\n Mem: shortSignal({\n index: 0,\n unsigned: true\n }),\n Gpu: shortSignal({\n index: 1,\n unsigned: true\n }),\n FanSpeed: shortSignal({\n index: 2,\n unsigned: true\n }),\n BatteryPercent: charSignal({\n index: 6,\n unsigned: true\n }),\n UsbOnline: boolSignal({\n index: 56\n }),\n Started: boolSignal({\n index: 57\n })\n};\n\nexport const thermalFreeSpace = {\n FreeSpace: longSignal({\n index: 0,\n unsigned: true,\n factor: 0.000000001\n })\n};\n\nexport const signalMap = {\n 'CarState:WheelSpeeds': wheelSpeeds,\n 'CarState:Ego': ego,\n 'CarState:Controls': controls,\n 'CarState:Flags': flags,\n 'UbloxGnss:MeasurementReport': ubloxGnss,\n 'Health:Data': health,\n 'Thermal:CPU': thermalCPU,\n 'Thermal:Data': thermalData,\n 'Thermal:FreeSpace': thermalFreeSpace\n};\n\nconst ADDRESS_LIST = [];\n\nObject.keys(signalMap).forEach((name) => {\n Object.keys(signalMap[name]).forEach((signal) => {\n signalMap[name][signal] = createSignalEntry({\n name: signal,\n ...signalMap[name][signal]\n });\n });\n addressForName(name);\n});\n\nfunction createSignalEntry(options) {\n return new Signal({\n name: options.name,\n startBit: options.startBit,\n size: options.size,\n isLittleEndian: false,\n isSigned: !options.unsigned,\n factor: options.factor || 1,\n offset: options.offset || 0,\n unit: options.unit || ''\n });\n}\n\nfunction longSignal(options) {\n return {\n ...options,\n size: 32,\n startBit: options.index * 32 + 7\n };\n}\n\nfunction shortSignal(options) {\n return {\n ...options,\n size: 16,\n startBit: options.index * 16 + 7\n };\n}\n\nfunction charSignal(options) {\n return {\n ...options,\n size: 8,\n startBit: options.index * 8 + 7\n };\n}\n\nfunction boolSignal(options) {\n return {\n ...options,\n size: 1,\n startBit: options.index,\n unsigned: true\n };\n}\n\nexport function addressForName(name) {\n const i = ADDRESS_LIST.indexOf(name);\n if (i === -1) {\n ADDRESS_LIST.push(name);\n return ADDRESS_LIST.indexOf(name) + 0x1000;\n }\n return i + 0x1000;\n}\n\nexport function nameForAddress(address) {\n if (address >= 0x1000) {\n return ADDRESS_LIST[address - 0x1000];\n }\n return null;\n}\n\nexport function isLogAddress(address) {\n return !!nameForAddress(address);\n}\n\nexport function frameForAddress(address) {\n const name = nameForAddress(address);\n return new Frame({\n id: name,\n name,\n size: 8,\n signals: signalMap[name]\n });\n}\n"],"sourceRoot":""}