Add eslint with explorer configuration (#26)
* Add eslint and run --fix * Remove precommit prettiermain
parent
8bcda7c579
commit
1be5544df3
|
@ -0,0 +1,5 @@
|
|||
node_modules/
|
||||
public/
|
||||
build/
|
||||
.storybook
|
||||
src/registerServiceWorker.js
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"parser": "babel-eslint",
|
||||
"extends": [
|
||||
"airbnb"
|
||||
],
|
||||
"rules": {
|
||||
"import/prefer-default-export": 0,
|
||||
"import/no-named-as-default": 0,
|
||||
"comma-dangle": 0,
|
||||
"react/jsx-filename-extension": 0, // .jsx should be better? But git diff will be crazy
|
||||
"react/forbid-prop-types": 0, // Too time consuming to map out types for now
|
||||
"react/require-default-props": 0,
|
||||
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }]
|
||||
},
|
||||
"env": {
|
||||
"browser": true
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"extends": "react-app",
|
||||
"rules": {
|
||||
"no-undef": 1
|
||||
},
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"globals": {
|
||||
"window": false
|
||||
}
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
const WorkerLoaderPlugin = require("craco-worker-loader");
|
||||
const SentryPlugin = require("craco-sentry-plugin");
|
||||
const WorkerLoaderPlugin = require('craco-worker-loader');
|
||||
const SentryPlugin = require('craco-sentry-plugin');
|
||||
|
||||
module.exports = function({ env }) {
|
||||
var plugins = [
|
||||
module.exports = function ({ env }) {
|
||||
const plugins = [
|
||||
{
|
||||
plugin: WorkerLoaderPlugin
|
||||
}
|
||||
];
|
||||
if (env === "production") {
|
||||
if (env === 'production') {
|
||||
// plugins.push({
|
||||
// plugin: SentryPlugin
|
||||
// });
|
||||
}
|
||||
return {
|
||||
plugins: plugins,
|
||||
plugins,
|
||||
webpack: {
|
||||
configure: (webpackConfig, { env, paths }) => {
|
||||
webpackConfig.output.globalObject = "this";
|
||||
webpackConfig.output.globalObject = 'this';
|
||||
webpackConfig.optimization.minimizer = webpackConfig.optimization.minimizer.map(
|
||||
function(plugin) {
|
||||
if (plugin.constructor.name !== "TerserPlugin") {
|
||||
(plugin) => {
|
||||
if (plugin.constructor.name !== 'TerserPlugin') {
|
||||
return plugin;
|
||||
}
|
||||
plugin.options.terserOptions.keep_fnames = true;
|
||||
|
|
10
package.json
10
package.json
|
@ -11,6 +11,7 @@
|
|||
"@craco/craco": "^5.5.0",
|
||||
"ap": "^0.2.0",
|
||||
"aphrodite": "^1.2.1",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"base64-inline-loader": "^1.1.0",
|
||||
"classnames": "^2.2.5",
|
||||
"clipboard": "^1.7.1",
|
||||
|
@ -22,6 +23,12 @@
|
|||
"emotion": "^8.0.12",
|
||||
"enzyme": "^3.2.0",
|
||||
"enzyme-adapter-react-16": "^1.1.0",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-config-airbnb": "^18.0.1",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-react": "^7.16.0",
|
||||
"eslint-plugin-react-hooks": "^2.1.2",
|
||||
"file-saver": "^1.3.3",
|
||||
"font-awesome": "^4.7.0",
|
||||
"github-api": "^3.0.0",
|
||||
|
@ -86,11 +93,10 @@
|
|||
"test-ci": "CI=true craco test --env=jsdom",
|
||||
"netlify-sass": "node-sass src/index.scss > src/index.css",
|
||||
"sass": "node-sass src/index.scss -o src && node-sass -w src/index.scss -o src",
|
||||
"precommit": "lint-staged",
|
||||
"deploy": "npm run build && gh-pages -d build"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx}": ["prettier --parser flow --write", "git add"],
|
||||
"*.{js,jsx}": ["eslint --fix", "git add"],
|
||||
"*.json": ["prettier --parser json --write", "git add"],
|
||||
"*.{graphql,gql}": ["prettier --parser graphql --write", "git add"],
|
||||
"*.{md,markdown}": ["prettier --parser markdown --write", "git add"],
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
import React, { Component } from "react";
|
||||
import Moment from "moment";
|
||||
import PropTypes from "prop-types";
|
||||
import cx from "classnames";
|
||||
import { createWriteStream } from "streamsaver";
|
||||
import Panda from "@commaai/pandajs";
|
||||
import CommaAuth from "@commaai/my-comma-auth";
|
||||
import { raw as RawDataApi, drives as DrivesApi } from "@commaai/comma-api";
|
||||
import React, { Component } from 'react';
|
||||
import Moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import { createWriteStream } from 'streamsaver';
|
||||
import Panda from '@commaai/pandajs';
|
||||
import CommaAuth from '@commaai/my-comma-auth';
|
||||
import { raw as RawDataApi, drives as DrivesApi } from '@commaai/comma-api';
|
||||
import {
|
||||
USE_UNLOGGER,
|
||||
PART_SEGMENT_LENGTH,
|
||||
STREAMING_WINDOW,
|
||||
GITHUB_AUTH_TOKEN_KEY
|
||||
} from "./config";
|
||||
import * as GithubAuth from "./api/github-auth";
|
||||
} from './config';
|
||||
import * as GithubAuth from './api/github-auth';
|
||||
|
||||
import DBC from "./models/can/dbc";
|
||||
import Meta from "./components/Meta";
|
||||
import Explorer from "./components/Explorer";
|
||||
import OnboardingModal from "./components/Modals/OnboardingModal";
|
||||
import SaveDbcModal from "./components/SaveDbcModal";
|
||||
import LoadDbcModal from "./components/LoadDbcModal";
|
||||
import debounce from "./utils/debounce";
|
||||
import EditMessageModal from "./components/EditMessageModal";
|
||||
import LoadingBar from "./components/LoadingBar";
|
||||
import DBC from './models/can/dbc';
|
||||
import Meta from './components/Meta';
|
||||
import Explorer from './components/Explorer';
|
||||
import OnboardingModal from './components/Modals/OnboardingModal';
|
||||
import SaveDbcModal from './components/SaveDbcModal';
|
||||
import LoadDbcModal from './components/LoadDbcModal';
|
||||
import debounce from './utils/debounce';
|
||||
import EditMessageModal from './components/EditMessageModal';
|
||||
import LoadingBar from './components/LoadingBar';
|
||||
import {
|
||||
persistDbc,
|
||||
fetchPersistedDbc,
|
||||
unpersistGithubAuthToken
|
||||
} from "./api/localstorage";
|
||||
import OpenDbc from "./api/OpenDbc";
|
||||
import UnloggerClient from "./api/unlogger";
|
||||
import * as ObjectUtils from "./utils/object";
|
||||
import { hash } from "./utils/string";
|
||||
import { modifyQueryParameters } from "./utils/url";
|
||||
} from './api/localstorage';
|
||||
import OpenDbc from './api/OpenDbc';
|
||||
import UnloggerClient from './api/unlogger';
|
||||
import * as ObjectUtils from './utils/object';
|
||||
import { hash } from './utils/string';
|
||||
import { modifyQueryParameters } from './utils/url';
|
||||
|
||||
const RLogDownloader = require("./workers/rlog-downloader.worker.js");
|
||||
const LogCSVDownloader = require("./workers/dbc-csv-downloader.worker.js");
|
||||
const MessageParser = require("./workers/message-parser.worker.js");
|
||||
const CanStreamerWorker = require("./workers/CanStreamerWorker.worker.js");
|
||||
const RLogDownloader = require('./workers/rlog-downloader.worker.js');
|
||||
const LogCSVDownloader = require('./workers/dbc-csv-downloader.worker.js');
|
||||
const MessageParser = require('./workers/message-parser.worker.js');
|
||||
const CanStreamerWorker = require('./workers/CanStreamerWorker.worker.js');
|
||||
|
||||
export default class CanExplorer extends Component {
|
||||
static propTypes = {
|
||||
|
@ -73,7 +73,7 @@ export default class CanExplorer extends Component {
|
|||
editMessageModalMessage: null,
|
||||
dbc: props.dbc ? props.dbc : new DBC(),
|
||||
dbcText: props.dbc ? props.dbc.text() : new DBC().text(),
|
||||
dbcFilename: props.dbcFilename ? props.dbcFilename : "New_DBC",
|
||||
dbcFilename: props.dbcFilename ? props.dbcFilename : 'New_DBC',
|
||||
dbcLastSaved: null,
|
||||
seekTime: 0,
|
||||
seekIndex: 0,
|
||||
|
@ -135,19 +135,19 @@ export default class CanExplorer extends Component {
|
|||
if (CommaAuth.isAuthenticated() && !name) {
|
||||
this.showOnboarding();
|
||||
} else if (
|
||||
this.props.max &&
|
||||
this.props.url &&
|
||||
!this.props.exp &&
|
||||
!this.props.sig
|
||||
this.props.max
|
||||
&& this.props.url
|
||||
&& !this.props.exp
|
||||
&& !this.props.sig
|
||||
) {
|
||||
// probably the demo!
|
||||
const { max, url } = this.props;
|
||||
const startTime = Moment(name, "YYYY-MM-DD--H-m-s");
|
||||
const startTime = Moment(name, 'YYYY-MM-DD--H-m-s');
|
||||
|
||||
const route = {
|
||||
fullname: dongleId + "|" + name,
|
||||
fullname: `${dongleId}|${name}`,
|
||||
proclog: max,
|
||||
url: url,
|
||||
url,
|
||||
start_time: startTime
|
||||
};
|
||||
this.setState(
|
||||
|
@ -158,15 +158,14 @@ export default class CanExplorer extends Component {
|
|||
this.initCanData
|
||||
);
|
||||
} else if (dongleId && name) {
|
||||
const routeName = dongleId + "|" + name;
|
||||
let urlPromise, logUrlsPromise;
|
||||
const routeName = `${dongleId}|${name}`;
|
||||
let urlPromise;
|
||||
let logUrlsPromise;
|
||||
|
||||
if (this.props.url) {
|
||||
urlPromise = Promise.resolve(this.props.url);
|
||||
} else {
|
||||
urlPromise = DrivesApi.getRouteInfo(routeName).then(function(route) {
|
||||
return route.url;
|
||||
});
|
||||
urlPromise = DrivesApi.getRouteInfo(routeName).then((route) => route.url);
|
||||
}
|
||||
|
||||
if (this.props.sig && this.props.exp) {
|
||||
|
@ -178,13 +177,13 @@ export default class CanExplorer extends Component {
|
|||
logUrlsPromise = RawDataApi.getLogUrls(routeName);
|
||||
}
|
||||
Promise.all([urlPromise, logUrlsPromise])
|
||||
.then(initData => {
|
||||
let [url, logUrls] = initData;
|
||||
.then((initData) => {
|
||||
const [url, logUrls] = initData;
|
||||
const newState = {
|
||||
route: {
|
||||
fullname: routeName,
|
||||
proclog: logUrls.length - 1,
|
||||
start_time: Moment(name, "YYYY-MM-DD--H-m-s"),
|
||||
start_time: Moment(name, 'YYYY-MM-DD--H-m-s'),
|
||||
url
|
||||
},
|
||||
currentParts: [
|
||||
|
@ -195,21 +194,19 @@ export default class CanExplorer extends Component {
|
|||
};
|
||||
this.setState(newState, this.initCanData);
|
||||
|
||||
DrivesApi.getShareSignature(routeName).then(shareSignature =>
|
||||
this.setState({
|
||||
shareUrl: modifyQueryParameters({
|
||||
add: {
|
||||
exp: shareSignature.exp,
|
||||
sig: shareSignature.sig,
|
||||
max: logUrls.length - 1,
|
||||
url
|
||||
},
|
||||
remove: [GITHUB_AUTH_TOKEN_KEY]
|
||||
})
|
||||
DrivesApi.getShareSignature(routeName).then((shareSignature) => this.setState({
|
||||
shareUrl: modifyQueryParameters({
|
||||
add: {
|
||||
exp: shareSignature.exp,
|
||||
sig: shareSignature.sig,
|
||||
max: logUrls.length - 1,
|
||||
url
|
||||
},
|
||||
remove: [GITHUB_AUTH_TOKEN_KEY]
|
||||
})
|
||||
);
|
||||
}));
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
this.showOnboarding();
|
||||
});
|
||||
|
@ -245,7 +242,12 @@ export default class CanExplorer extends Component {
|
|||
}
|
||||
);
|
||||
} else {
|
||||
this.setState({ dbc, dbcFilename, dbcText: dbc.text(), messages: {} });
|
||||
this.setState({
|
||||
dbc,
|
||||
dbcFilename,
|
||||
dbcText: dbc.text(),
|
||||
messages: {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,10 +264,10 @@ export default class CanExplorer extends Component {
|
|||
// }
|
||||
|
||||
downloadLogAsCSV() {
|
||||
console.log("downloadLogAsCSV:start");
|
||||
console.log('downloadLogAsCSV:start');
|
||||
const { dbcFilename } = this.state;
|
||||
const fileStream = createWriteStream(
|
||||
`${dbcFilename.replace(/\.dbc/g, "-")}${+new Date()}.csv`
|
||||
`${dbcFilename.replace(/\.dbc/g, '-')}${+new Date()}.csv`
|
||||
);
|
||||
const writer = fileStream.getWriter();
|
||||
const encoder = new TextEncoder();
|
||||
|
@ -278,15 +280,16 @@ export default class CanExplorer extends Component {
|
|||
function dataHandler(e) {
|
||||
const { logData, shouldClose, progress } = e.data;
|
||||
if (shouldClose) {
|
||||
console.log("downloadLogAsCSV:close");
|
||||
console.log('downloadLogAsCSV:close');
|
||||
writer.close();
|
||||
return;
|
||||
}
|
||||
console.log("CSV export progress:", progress);
|
||||
const uint8array = encoder.encode(logData + "\n");
|
||||
console.log('CSV export progress:', progress);
|
||||
const uint8array = encoder.encode(`${logData}\n`);
|
||||
writer.write(uint8array);
|
||||
}
|
||||
}
|
||||
|
||||
downloadRawLogAsCSV(handler) {
|
||||
return this.downloadLiveLogAsCSV(handler);
|
||||
}
|
||||
|
@ -301,8 +304,8 @@ export default class CanExplorer extends Component {
|
|||
worker.onmessage = handler;
|
||||
|
||||
worker.postMessage({
|
||||
data: Object.keys(this.state.messages).map(sourceId => {
|
||||
var source = this.state.messages[sourceId];
|
||||
data: Object.keys(this.state.messages).map((sourceId) => {
|
||||
const source = this.state.messages[sourceId];
|
||||
return {
|
||||
id: source.id,
|
||||
bus: source.bus,
|
||||
|
@ -321,16 +324,16 @@ export default class CanExplorer extends Component {
|
|||
options = options || {};
|
||||
|
||||
const messages = { ...this.state.messages };
|
||||
for (var key in newMessages) {
|
||||
for (const key in newMessages) {
|
||||
// add message
|
||||
if (options.replace !== true && key in messages) {
|
||||
// should merge here instead of concat
|
||||
// assumes messages are always sequential
|
||||
let msgEntries = messages[key].entries;
|
||||
let newMsgEntries = newMessages[key].entries;
|
||||
let msgLength = msgEntries.length;
|
||||
let newMsgLength = newMsgEntries.length;
|
||||
let entryLength = msgLength + newMsgLength;
|
||||
const msgEntries = messages[key].entries;
|
||||
const newMsgEntries = newMessages[key].entries;
|
||||
const msgLength = msgEntries.length;
|
||||
const newMsgLength = newMsgEntries.length;
|
||||
const entryLength = msgLength + newMsgLength;
|
||||
messages[key].entries = Array(entryLength);
|
||||
|
||||
let msgIndex = 0;
|
||||
|
@ -351,8 +354,7 @@ export default class CanExplorer extends Component {
|
|||
messages[key].entries[i] = newMsgEntries[newMsgIndex++];
|
||||
}
|
||||
}
|
||||
messages[key].byteStateChangeCounts =
|
||||
newMessages[key].byteStateChangeCounts;
|
||||
messages[key].byteStateChangeCounts = newMessages[key].byteStateChangeCounts;
|
||||
} else {
|
||||
messages[key] = newMessages[key];
|
||||
messages[key].frame = this.state.dbc.getMessageFrame(
|
||||
|
@ -365,15 +367,15 @@ export default class CanExplorer extends Component {
|
|||
}
|
||||
|
||||
cancelWorker(workerHash) {
|
||||
let currentWorkers = { ...this.state.currentWorkers };
|
||||
let { worker, part } = currentWorkers[workerHash];
|
||||
let loadingParts = this.state.loadingParts.filter(p => p !== part);
|
||||
let loadedParts = this.state.loadedParts.filter(p => p !== part);
|
||||
const currentWorkers = { ...this.state.currentWorkers };
|
||||
const { worker, part } = currentWorkers[workerHash];
|
||||
const loadingParts = this.state.loadingParts.filter((p) => p !== part);
|
||||
const loadedParts = this.state.loadedParts.filter((p) => p !== part);
|
||||
delete currentWorkers[workerHash];
|
||||
|
||||
console.log("Stoping worker", workerHash, "for part", part);
|
||||
console.log('Stoping worker', workerHash, 'for part', part);
|
||||
worker.postMessage({
|
||||
action: "terminate"
|
||||
action: 'terminate'
|
||||
});
|
||||
|
||||
this.setState({
|
||||
|
@ -385,16 +387,16 @@ export default class CanExplorer extends Component {
|
|||
|
||||
spawnWorker(options) {
|
||||
let { currentParts, currentWorkers } = this.state;
|
||||
console.log("Checking worker for", currentParts);
|
||||
console.log('Checking worker for', currentParts);
|
||||
if (!this.state.isLoading) {
|
||||
this.setState({ isLoading: true });
|
||||
}
|
||||
const [minPart, maxPart] = currentParts;
|
||||
// cancel old workers that are still loading data no longer inside the window
|
||||
Object.keys(currentWorkers).forEach(workerHash => {
|
||||
Object.keys(currentWorkers).forEach((workerHash) => {
|
||||
if (
|
||||
currentWorkers[workerHash].part < minPart ||
|
||||
currentWorkers[workerHash].part > maxPart
|
||||
currentWorkers[workerHash].part < minPart
|
||||
|| currentWorkers[workerHash].part > maxPart
|
||||
) {
|
||||
this.cancelWorker(workerHash);
|
||||
}
|
||||
|
@ -406,12 +408,12 @@ export default class CanExplorer extends Component {
|
|||
|
||||
// clean this up just in case, the cancel process above *should* have already done this
|
||||
// they have at most 4 entries so it's trivial
|
||||
loadingParts = loadingParts.filter(p => p >= minPart && p <= maxPart);
|
||||
loadedParts = loadedParts.filter(p => p >= minPart && p <= maxPart);
|
||||
loadingParts = loadingParts.filter((p) => p >= minPart && p <= maxPart);
|
||||
loadedParts = loadedParts.filter((p) => p >= minPart && p <= maxPart);
|
||||
|
||||
let part = -1;
|
||||
let allWorkerParts = Object.keys(currentWorkers).map(
|
||||
i => currentWorkers[i].part
|
||||
const allWorkerParts = Object.keys(currentWorkers).map(
|
||||
(i) => currentWorkers[i].part
|
||||
);
|
||||
|
||||
for (let partOffset = 0; partOffset <= maxPart - minPart; ++partOffset) {
|
||||
|
@ -425,15 +427,15 @@ export default class CanExplorer extends Component {
|
|||
}
|
||||
}
|
||||
if (part === -1) {
|
||||
console.log("Loading complete");
|
||||
console.log('Loading complete');
|
||||
this.setState({ isLoading: false });
|
||||
return;
|
||||
}
|
||||
console.log("Starting worker for part", part);
|
||||
console.log('Starting worker for part', part);
|
||||
// options is object of {part, prevMsgEntries, spawnWorkerHash, prepend}
|
||||
options = options || {};
|
||||
let prevMsgEntries = options.prevMsgEntries;
|
||||
let prepend = false;
|
||||
let { prevMsgEntries } = options;
|
||||
const prepend = false;
|
||||
|
||||
const {
|
||||
dbc,
|
||||
|
@ -446,19 +448,19 @@ export default class CanExplorer extends Component {
|
|||
|
||||
if (!prevMsgEntries) {
|
||||
// we have previous messages loaded
|
||||
let { messages } = this.state;
|
||||
let canStartTime = firstCanTime - canFrameOffset;
|
||||
const { messages } = this.state;
|
||||
const canStartTime = firstCanTime - canFrameOffset;
|
||||
prevMsgEntries = {};
|
||||
Object.keys(messages).forEach(function(key) {
|
||||
let entries = messages[key].entries;
|
||||
Object.keys(messages).forEach((key) => {
|
||||
const { entries } = messages[key];
|
||||
prevMsgEntries[key] = entries[entries.length - 1];
|
||||
});
|
||||
}
|
||||
|
||||
// var worker = new CanFetcher();
|
||||
var worker = new RLogDownloader();
|
||||
const worker = new RLogDownloader();
|
||||
|
||||
let spawnWorkerHash = hash(Math.random().toString(16));
|
||||
const spawnWorkerHash = hash(Math.random().toString(16));
|
||||
currentWorkers[spawnWorkerHash] = {
|
||||
part,
|
||||
worker
|
||||
|
@ -471,9 +473,9 @@ export default class CanExplorer extends Component {
|
|||
loadingParts
|
||||
});
|
||||
|
||||
worker.onmessage = e => {
|
||||
worker.onmessage = (e) => {
|
||||
if (this.state.currentWorkers[spawnWorkerHash] === undefined) {
|
||||
console.log("Worker was canceled");
|
||||
console.log('Worker was canceled');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -495,16 +497,15 @@ export default class CanExplorer extends Component {
|
|||
maxByteStateChangeCount
|
||||
);
|
||||
const prevMsgEntries = {};
|
||||
for (let key in newMessages) {
|
||||
prevMsgEntries[key] =
|
||||
newMessages[key].entries[newMessages[key].entries.length - 1];
|
||||
for (const key in newMessages) {
|
||||
prevMsgEntries[key] = newMessages[key].entries[newMessages[key].entries.length - 1];
|
||||
}
|
||||
|
||||
if (!isFinished) {
|
||||
this.setState({ messages });
|
||||
} else {
|
||||
let loadingParts = this.state.loadingParts.filter(p => p !== part);
|
||||
let loadedParts = [part, ...this.state.loadedParts];
|
||||
const loadingParts = this.state.loadingParts.filter((p) => p !== part);
|
||||
const loadedParts = [part, ...this.state.loadedParts];
|
||||
|
||||
this.setState(
|
||||
{
|
||||
|
@ -537,7 +538,7 @@ export default class CanExplorer extends Component {
|
|||
// data that is used
|
||||
dbcText: dbc.text(),
|
||||
route: route.fullname,
|
||||
part: part,
|
||||
part,
|
||||
canStartTime: firstCanTime != null ? firstCanTime - canFrameOffset : null,
|
||||
prevMsgEntries,
|
||||
maxByteStateChangeCount
|
||||
|
@ -553,11 +554,11 @@ export default class CanExplorer extends Component {
|
|||
showEditMessageModal
|
||||
} = this.state;
|
||||
return (
|
||||
showOnboarding ||
|
||||
showLoadDbc ||
|
||||
showSaveDbc ||
|
||||
showAddSignal ||
|
||||
showEditMessageModal
|
||||
showOnboarding
|
||||
|| showLoadDbc
|
||||
|| showSaveDbc
|
||||
|| showAddSignal
|
||||
|| showEditMessageModal
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -589,8 +590,8 @@ export default class CanExplorer extends Component {
|
|||
this.setState({ isLoading: true });
|
||||
|
||||
const { dbc } = this.state;
|
||||
var worker = new MessageParser();
|
||||
worker.onmessage = e => {
|
||||
const worker = new MessageParser();
|
||||
worker.onmessage = (e) => {
|
||||
let messages = e.data;
|
||||
messages = this.addAndRehydrateMessages(messages, { replace: true });
|
||||
|
||||
|
@ -616,7 +617,7 @@ export default class CanExplorer extends Component {
|
|||
if (route) {
|
||||
persistDbc(route.fullname, { dbcFilename, dbc });
|
||||
} else {
|
||||
persistDbc("live", { dbcFilename, dbc });
|
||||
persistDbc('live', { dbcFilename, dbc });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,19 +636,17 @@ export default class CanExplorer extends Component {
|
|||
|
||||
messages[message.id] = newMessage;
|
||||
|
||||
this.setState({ dbc, dbcText: dbc.text() }, () =>
|
||||
this.reparseMessages(messages)
|
||||
);
|
||||
this.setState({ dbc, dbcText: dbc.text() }, () => this.reparseMessages(messages));
|
||||
}
|
||||
|
||||
partChangeDebounced = debounce(() => {
|
||||
let [minPart, maxPart] = this.state.currentParts;
|
||||
let messages = { ...this.state.messages };
|
||||
const [minPart, maxPart] = this.state.currentParts;
|
||||
const messages = { ...this.state.messages };
|
||||
// update messages to only preserve entries in new part range
|
||||
let minTime = minPart * 60;
|
||||
let maxTime = maxPart * 60 + 60;
|
||||
Object.keys(messages).forEach(key => {
|
||||
let entries = messages[key].entries;
|
||||
const minTime = minPart * 60;
|
||||
const maxTime = maxPart * 60 + 60;
|
||||
Object.keys(messages).forEach((key) => {
|
||||
const { entries } = messages[key];
|
||||
let minIndex = 0;
|
||||
let maxIndex = entries.length - 1;
|
||||
while (minIndex < entries.length && entries[minIndex].relTime < minTime) {
|
||||
|
@ -669,14 +668,16 @@ export default class CanExplorer extends Component {
|
|||
}, 500);
|
||||
|
||||
onPartChange(part) {
|
||||
let { currentParts, currentPart, canFrameOffset, route } = this.state;
|
||||
let {
|
||||
currentParts, currentPart, canFrameOffset, route
|
||||
} = this.state;
|
||||
if (canFrameOffset === -1 || part === currentPart) {
|
||||
return;
|
||||
}
|
||||
|
||||
// determine new parts to load, whether to prepend or append
|
||||
let maxPart = Math.min(route.proclog, part + 1);
|
||||
let minPart = Math.max(0, maxPart - PART_SEGMENT_LENGTH + 1);
|
||||
const minPart = Math.max(0, maxPart - PART_SEGMENT_LENGTH + 1);
|
||||
if (minPart === 0) {
|
||||
maxPart = Math.min(route.proclog, 2);
|
||||
}
|
||||
|
@ -687,9 +688,9 @@ export default class CanExplorer extends Component {
|
|||
currentPart = part;
|
||||
|
||||
if (
|
||||
currentPart !== this.state.currentPart ||
|
||||
currentParts[0] !== this.state.currentParts[0] ||
|
||||
currentParts[1] !== this.state.currentParts[1]
|
||||
currentPart !== this.state.currentPart
|
||||
|| currentParts[0] !== this.state.currentParts[0]
|
||||
|| currentParts[1] !== this.state.currentParts[1]
|
||||
) {
|
||||
// update state then load new parts
|
||||
this.setState({ currentParts, currentPart }, this.partChangeDebounced);
|
||||
|
@ -715,9 +716,11 @@ export default class CanExplorer extends Component {
|
|||
}
|
||||
|
||||
onMessageFrameEdited(messageFrame) {
|
||||
const { messages, dbcFilename, dbc, editMessageModalMessage } = this.state;
|
||||
const {
|
||||
messages, dbcFilename, dbc, editMessageModalMessage
|
||||
} = this.state;
|
||||
|
||||
const message = Object.assign({}, messages[editMessageModalMessage]);
|
||||
const message = { ...messages[editMessageModalMessage] };
|
||||
message.frame = messageFrame;
|
||||
dbc.messages.set(messageFrame.id, messageFrame);
|
||||
this.persistDbc({ dbcFilename, dbc });
|
||||
|
@ -730,8 +733,8 @@ export default class CanExplorer extends Component {
|
|||
onSeek(seekIndex, seekTime) {
|
||||
this.setState({ seekIndex, seekTime });
|
||||
|
||||
let { currentPart } = this.state;
|
||||
let part = ~~(seekTime / 60);
|
||||
const { currentPart } = this.state;
|
||||
const part = ~~(seekTime / 60);
|
||||
if (part !== currentPart) {
|
||||
this.onPartChange(part);
|
||||
}
|
||||
|
@ -745,7 +748,7 @@ export default class CanExplorer extends Component {
|
|||
const msg = this.state.messages[this.state.selectedMessage];
|
||||
let seekIndex;
|
||||
if (msg) {
|
||||
seekIndex = msg.entries.findIndex(e => e.relTime >= seekTime);
|
||||
seekIndex = msg.entries.findIndex((e) => e.relTime >= seekTime);
|
||||
if (seekIndex === -1) {
|
||||
seekIndex = 0;
|
||||
}
|
||||
|
@ -761,7 +764,7 @@ export default class CanExplorer extends Component {
|
|||
const msg = messages[msgKey];
|
||||
|
||||
if (seekTime > 0 && msg.entries.length > 0) {
|
||||
seekIndex = msg.entries.findIndex(e => e.relTime >= seekTime);
|
||||
seekIndex = msg.entries.findIndex((e) => e.relTime >= seekTime);
|
||||
if (seekIndex === -1) {
|
||||
seekIndex = 0;
|
||||
}
|
||||
|
@ -785,7 +788,7 @@ export default class CanExplorer extends Component {
|
|||
return (
|
||||
<a
|
||||
href={GithubAuth.authorizeUrl(
|
||||
route && route.fullname ? route.fullname : ""
|
||||
route && route.fullname ? route.fullname : ''
|
||||
)}
|
||||
className="button button--dark button--inline"
|
||||
>
|
||||
|
@ -847,7 +850,7 @@ export default class CanExplorer extends Component {
|
|||
}
|
||||
|
||||
enforceStreamingMessageWindow(messages) {
|
||||
let messageIds = Object.keys(messages);
|
||||
const messageIds = Object.keys(messages);
|
||||
for (let i = 0; i < messageIds.length; i++) {
|
||||
const messageId = messageIds[i];
|
||||
const message = messages[messageId];
|
||||
|
@ -886,8 +889,8 @@ export default class CanExplorer extends Component {
|
|||
messages = this.enforceStreamingMessageWindow(messages);
|
||||
let { seekIndex, selectedMessages } = this.state;
|
||||
if (
|
||||
selectedMessages.length > 0 &&
|
||||
messages[selectedMessages[0]] !== undefined
|
||||
selectedMessages.length > 0
|
||||
&& messages[selectedMessages[0]] !== undefined
|
||||
) {
|
||||
seekIndex = Math.max(0, messages[selectedMessages[0]].entries.length - 1);
|
||||
}
|
||||
|
@ -908,16 +911,16 @@ export default class CanExplorer extends Component {
|
|||
async handlePandaConnect(e) {
|
||||
this.setState({ attemptingPandaConnection: true, live: true });
|
||||
|
||||
const persistedDbc = fetchPersistedDbc("live");
|
||||
const persistedDbc = fetchPersistedDbc('live');
|
||||
if (persistedDbc) {
|
||||
let { dbc, dbcText } = persistedDbc;
|
||||
const { dbc, dbcText } = persistedDbc;
|
||||
this.setState({ dbc, dbcText });
|
||||
}
|
||||
this.canStreamerWorker = new CanStreamerWorker();
|
||||
this.canStreamerWorker.onmessage = this.onStreamedCanMessagesProcessed;
|
||||
|
||||
// if any errors go off during connection, mark as not trying to connect anymore...
|
||||
let unlisten = this.pandaReader.onError(err => {
|
||||
const unlisten = this.pandaReader.onError((err) => {
|
||||
console.error(err.stack || err);
|
||||
this.setState({ attemptingPandaConnection: false });
|
||||
});
|
||||
|
@ -943,7 +946,7 @@ export default class CanExplorer extends Component {
|
|||
return (
|
||||
<div
|
||||
id="cabana"
|
||||
className={cx({ "is-showing-modal": this.showingModal() })}
|
||||
className={cx({ 'is-showing-modal': this.showingModal() })}
|
||||
>
|
||||
{this.state.isLoading ? (
|
||||
<LoadingBar isLoading={this.state.isLoading} />
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
global.__JEST__ = 1;
|
||||
import DBC from "../../models/can/dbc";
|
||||
import Signal from "../../models/can/signal";
|
||||
import DBC from '../../models/can/dbc';
|
||||
import Signal from '../../models/can/signal';
|
||||
|
||||
test("setting signals should create a message", () => {
|
||||
global.__JEST__ = 1;
|
||||
|
||||
test('setting signals should create a message', () => {
|
||||
const dbc = new DBC();
|
||||
dbc.setSignals(100, { "My Signal": new Signal({ name: "My Signal" }) });
|
||||
dbc.setSignals(100, { 'My Signal': new Signal({ name: 'My Signal' }) });
|
||||
|
||||
expect(dbc.messages.has(100)).toBe(true);
|
||||
});
|
||||
|
||||
test("setting signals should update DBC.boardUnits", () => {
|
||||
test('setting signals should update DBC.boardUnits', () => {
|
||||
const dbc = new DBC();
|
||||
dbc.setSignals(100, {
|
||||
"My Signal": new Signal({ name: "My Signal", receiver: ["NEO"] })
|
||||
'My Signal': new Signal({ name: 'My Signal', receiver: ['NEO'] })
|
||||
});
|
||||
|
||||
expect(dbc.boardUnits.map(bu => bu.name).indexOf("NEO")).toBe(0);
|
||||
expect(dbc.boardUnits.map((bu) => bu.name).indexOf('NEO')).toBe(0);
|
||||
});
|
||||
|
||||
test("adding a signal should update DBC.boardUnits", () => {
|
||||
test('adding a signal should update DBC.boardUnits', () => {
|
||||
const dbc = new DBC();
|
||||
dbc.createFrame(100);
|
||||
dbc.addSignal(100, new Signal({ name: "My Signal", receiver: ["NEO"] }));
|
||||
dbc.addSignal(100, new Signal({ name: 'My Signal', receiver: ['NEO'] }));
|
||||
|
||||
expect(dbc.boardUnits.map(bu => bu.name).indexOf("NEO")).toBe(0);
|
||||
expect(dbc.boardUnits.map((bu) => bu.name).indexOf('NEO')).toBe(0);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import DBC, { swapOrder } from '../../models/can/dbc';
|
||||
import Signal from '../../models/can/signal';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
import DBC, { swapOrder } from "../../models/can/dbc";
|
||||
import Signal from "../../models/can/signal";
|
||||
|
||||
const DBC_MESSAGE_DEF = `BO_ 228 STEERING_CONTROL: 5 ADAS
|
||||
SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS
|
||||
|
@ -145,7 +146,7 @@ BO_ 464 WHEEL_SPEEDS: 8 VSA
|
|||
`;
|
||||
|
||||
const steerTorqueSignal = new Signal({
|
||||
name: "STEER_TORQUE",
|
||||
name: 'STEER_TORQUE',
|
||||
startBit: 7,
|
||||
size: 16,
|
||||
isLittleEndian: false,
|
||||
|
@ -154,165 +155,165 @@ const steerTorqueSignal = new Signal({
|
|||
offset: 0,
|
||||
min: -3840,
|
||||
max: 3840,
|
||||
receiver: ["EPS"],
|
||||
unit: ""
|
||||
receiver: ['EPS'],
|
||||
unit: ''
|
||||
});
|
||||
|
||||
function dbcInt32SignalValue(dbc, signalSpec, hex) {
|
||||
// expects hex string to represent 8 bytes, left-justified with zeroes if frame size is smaller
|
||||
const buffer = Buffer.from(hex, "hex");
|
||||
const buffer = Buffer.from(hex, 'hex');
|
||||
|
||||
return dbc.valueForInt32Signal(signalSpec, buffer);
|
||||
}
|
||||
|
||||
test("DBC parses steering control message", () => {
|
||||
test('DBC parses steering control message', () => {
|
||||
const dbcParsed = new DBC(DBC_MESSAGE_DEF);
|
||||
const { signals } = dbcParsed.getMessageFrame(228);
|
||||
|
||||
expect(Object.keys(signals).length).toBe(6);
|
||||
expect(signals["STEER_TORQUE"].equals(steerTorqueSignal)).toBe(true);
|
||||
expect(signals.STEER_TORQUE.equals(steerTorqueSignal)).toBe(true);
|
||||
});
|
||||
|
||||
test("DBC parses signal comment", () => {
|
||||
test('DBC parses signal comment', () => {
|
||||
const dbcParsed = new DBC(DBC_SIGNAL_WITH_COMMENT);
|
||||
const { signals } = dbcParsed.getMessageFrame(228);
|
||||
|
||||
expect(signals.STEER_TORQUE.comment).toEqual(
|
||||
"steer torque is the amount of torque in Nm applied"
|
||||
'steer torque is the amount of torque in Nm applied'
|
||||
);
|
||||
});
|
||||
|
||||
test("DBC parses multi-line signal comment", () => {
|
||||
test('DBC parses multi-line signal comment', () => {
|
||||
const dbcParsed = new DBC(DBC_SIGNAL_WITH_MULTI_LINE_COMMENT);
|
||||
const { signals } = dbcParsed.getMessageFrame(228);
|
||||
|
||||
expect(signals.STEER_TORQUE.comment).toEqual(
|
||||
"steer torque is the\namount of torque in Nm applied"
|
||||
'steer torque is the\namount of torque in Nm applied'
|
||||
);
|
||||
});
|
||||
|
||||
test("DBC parses message comment", () => {
|
||||
test('DBC parses message comment', () => {
|
||||
const dbcParsed = new DBC(DBC_MESSAGE_WITH_COMMENT);
|
||||
const msg = dbcParsed.getMessageFrame(228);
|
||||
|
||||
expect(msg.comment).toEqual("this message contains steer torque information");
|
||||
expect(msg.comment).toEqual('this message contains steer torque information');
|
||||
});
|
||||
|
||||
test("DBC parses multi-line message comment", () => {
|
||||
test('DBC parses multi-line message comment', () => {
|
||||
const dbcParsed = new DBC(DBC_MESSAGE_WITH_MULTI_LINE_COMMENT);
|
||||
const msg = dbcParsed.getMessageFrame(228);
|
||||
|
||||
expect(msg.comment).toEqual(
|
||||
"this message contains\nsteer torque information"
|
||||
'this message contains\nsteer torque information'
|
||||
);
|
||||
});
|
||||
|
||||
test("DBC parses board unit names", () => {
|
||||
test('DBC parses board unit names', () => {
|
||||
const dbcParsed = new DBC(DBC_BOARD_UNITS);
|
||||
expect(dbcParsed.boardUnits[0].name).toEqual("first_board_unit");
|
||||
expect(dbcParsed.boardUnits[1].name).toEqual("second_board_unit");
|
||||
expect(dbcParsed.boardUnits[0].name).toEqual('first_board_unit');
|
||||
expect(dbcParsed.boardUnits[1].name).toEqual('second_board_unit');
|
||||
});
|
||||
|
||||
test("DBC parses board unit comments", () => {
|
||||
test('DBC parses board unit comments', () => {
|
||||
const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT);
|
||||
expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit comment");
|
||||
expect(dbcParsed.boardUnits[0].comment).toEqual('first board unit comment');
|
||||
});
|
||||
|
||||
test("DBC parses multi-line board unit comments", () => {
|
||||
test('DBC parses multi-line board unit comments', () => {
|
||||
const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT_LINES);
|
||||
expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit\ncomment");
|
||||
expect(dbcParsed.boardUnits[0].comment).toEqual('first board unit\ncomment');
|
||||
});
|
||||
|
||||
test("DBC parses signal value descriptions", () => {
|
||||
test('DBC parses signal value descriptions', () => {
|
||||
const dbcParsed = new DBC(DBC_SIGNALS_WITH_VAL);
|
||||
const { signals } = dbcParsed.getMessageFrame(228);
|
||||
|
||||
const expectedTorqueRequestVals = new Map([
|
||||
["1", "requesting torque"],
|
||||
["0", "not requesting torque"]
|
||||
['1', 'requesting torque'],
|
||||
['0', 'not requesting torque']
|
||||
]);
|
||||
expect(signals.STEER_TORQUE_REQUEST.valueDescriptions).toEqual(
|
||||
expectedTorqueRequestVals
|
||||
);
|
||||
});
|
||||
|
||||
test("DBC parses value tables", () => {
|
||||
test('DBC parses value tables', () => {
|
||||
const dbcParsed = new DBC(DBC_VALUE_TABLE);
|
||||
const stateTableEntries = [
|
||||
["4", "DI_STATE_ENABLE"],
|
||||
["3", "DI_STATE_FAULT"],
|
||||
["2", "DI_STATE_CLEAR_FAULT"],
|
||||
["1", "DI_STATE_STANDBY"],
|
||||
["0", "DI_STATE_PREAUTH"]
|
||||
['4', 'DI_STATE_ENABLE'],
|
||||
['3', 'DI_STATE_FAULT'],
|
||||
['2', 'DI_STATE_CLEAR_FAULT'],
|
||||
['1', 'DI_STATE_STANDBY'],
|
||||
['0', 'DI_STATE_PREAUTH']
|
||||
];
|
||||
const stateTable = new Map(stateTableEntries);
|
||||
const speedUnitsEntries = [["1", "DI_SPEED_KPH"], ["0", "DI_SPEED_MPH"]];
|
||||
const speedUnitsEntries = [['1', 'DI_SPEED_KPH'], ['0', 'DI_SPEED_MPH']];
|
||||
const speedUnitsTable = new Map(speedUnitsEntries);
|
||||
|
||||
const valueTableEntries = Array.from(dbcParsed.valueTables.entries());
|
||||
expect(valueTableEntries[0]).toEqual(["DI_state", stateTable]);
|
||||
expect(valueTableEntries[1]).toEqual(["DI_speedUnits", speedUnitsTable]);
|
||||
expect(valueTableEntries[0]).toEqual(['DI_state', stateTable]);
|
||||
expect(valueTableEntries[1]).toEqual(['DI_speedUnits', speedUnitsTable]);
|
||||
});
|
||||
|
||||
test("swapOrder properly converts little endian to big endian", () => {
|
||||
const littleEndianHex = "e2d62a0bd0d3b5e5";
|
||||
const bigEndianHex = "e5b5d3d00b2ad6e2";
|
||||
test('swapOrder properly converts little endian to big endian', () => {
|
||||
const littleEndianHex = 'e2d62a0bd0d3b5e5';
|
||||
const bigEndianHex = 'e5b5d3d00b2ad6e2';
|
||||
|
||||
const littleEndianHexSwapped = swapOrder(littleEndianHex, 16, 2);
|
||||
|
||||
expect(littleEndianHexSwapped == bigEndianHex).toBe(true);
|
||||
});
|
||||
|
||||
test("int32 parser produces correct value for steer torque signal", () => {
|
||||
test('int32 parser produces correct value for steer torque signal', () => {
|
||||
const dbc = new DBC(DBC_MESSAGE_DEF);
|
||||
|
||||
const hex = "e2d62a0bd0d3b5e5";
|
||||
const hex = 'e2d62a0bd0d3b5e5';
|
||||
const value = dbcInt32SignalValue(
|
||||
dbc,
|
||||
dbc.getMessageFrame(228).signals["STEER_TORQUE"],
|
||||
dbc.getMessageFrame(228).signals.STEER_TORQUE,
|
||||
hex
|
||||
);
|
||||
|
||||
expect(value).toBe(-7466);
|
||||
});
|
||||
|
||||
test("int64 parser produces correct value for steer torque signal", () => {
|
||||
test('int64 parser produces correct value for steer torque signal', () => {
|
||||
const dbc = new DBC(DBC_MESSAGE_DEF);
|
||||
|
||||
const hex = "e2d62a0bd0d3b5e5";
|
||||
const hex = 'e2d62a0bd0d3b5e5';
|
||||
const value = dbc.valueForInt64Signal(steerTorqueSignal, hex);
|
||||
|
||||
expect(value).toBe(-7466);
|
||||
});
|
||||
|
||||
test("int32 parser produces correct value for wheel speeds", () => {
|
||||
test('int32 parser produces correct value for wheel speeds', () => {
|
||||
const dbc = new DBC(DBC_WHEEL_SPEEDS);
|
||||
|
||||
const hex = "36806cd8d8f1b0b7";
|
||||
const hex = '36806cd8d8f1b0b7';
|
||||
const rearRight = dbcInt32SignalValue(
|
||||
dbc,
|
||||
dbc.getMessageFrame(464).signals["WHEEL_SPEED_RR"],
|
||||
dbc.getMessageFrame(464).signals.WHEEL_SPEED_RR,
|
||||
hex
|
||||
);
|
||||
expect(rearRight).toBe(69.23);
|
||||
|
||||
const rearLeft = dbcInt32SignalValue(
|
||||
dbc,
|
||||
dbc.getMessageFrame(464).signals["WHEEL_SPEED_RL"],
|
||||
dbc.getMessageFrame(464).signals.WHEEL_SPEED_RL,
|
||||
hex
|
||||
);
|
||||
expect(rearLeft).toBe(69.42);
|
||||
|
||||
const frontLeft = dbcInt32SignalValue(
|
||||
dbc,
|
||||
dbc.getMessageFrame(464).signals["WHEEL_SPEED_FL"],
|
||||
dbc.getMessageFrame(464).signals.WHEEL_SPEED_FL,
|
||||
hex
|
||||
);
|
||||
expect(frontLeft).toBe(69.76);
|
||||
|
||||
const frontRight = dbcInt32SignalValue(
|
||||
dbc,
|
||||
dbc.getMessageFrame(464).signals["WHEEL_SPEED_FR"],
|
||||
dbc.getMessageFrame(464).signals.WHEEL_SPEED_FR,
|
||||
hex
|
||||
);
|
||||
expect(frontRight).toBe(69.66);
|
||||
|
@ -323,12 +324,12 @@ BO_ 768 NEW_MSG_1: 8 XXX
|
|||
SG_ NEW_SIGNAL_1 : 37|1@1+ (1,0) [0|1] "" XXX
|
||||
`;
|
||||
|
||||
test("int32 parsers produces correct value for binary little endian signal", () => {
|
||||
test('int32 parsers produces correct value for binary little endian signal', () => {
|
||||
const dbc = new DBC(DBC_BINARY_LE_SIGNAL);
|
||||
const signalSpec = dbc.getMessageFrame(768).signals["NEW_SIGNAL_1"];
|
||||
const signalSpec = dbc.getMessageFrame(768).signals.NEW_SIGNAL_1;
|
||||
|
||||
const hexDataSet = "0000000020000000";
|
||||
const hexDataNotSet = "0000000000000000";
|
||||
const hexDataSet = '0000000020000000';
|
||||
const hexDataNotSet = '0000000000000000';
|
||||
|
||||
const setValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSet, 8);
|
||||
const notSetValue = dbcInt32SignalValue(dbc, signalSpec, hexDataNotSet, 8);
|
||||
|
@ -341,11 +342,11 @@ const DBC_TWO_BIT_LE_SIGNAL = `
|
|||
BO_ 768 NEW_MSG_1: 8 XXX
|
||||
SG_ NEW_SIGNAL_1 : 35|2@1+ (1,0) [0|3] "" XXX
|
||||
`;
|
||||
test("int32 parser produces correct value for 2-bit little endian signal spanning words", () => {
|
||||
test('int32 parser produces correct value for 2-bit little endian signal spanning words', () => {
|
||||
const dbc = new DBC(DBC_TWO_BIT_LE_SIGNAL);
|
||||
const signalSpec = dbc.getMessageFrame(768).signals["NEW_SIGNAL_1"];
|
||||
const signalSpec = dbc.getMessageFrame(768).signals.NEW_SIGNAL_1;
|
||||
|
||||
const hexData = "00000001f8000000";
|
||||
const hexData = '00000001f8000000';
|
||||
|
||||
const value = dbcInt32SignalValue(dbc, signalSpec, hexData, 8);
|
||||
expect(value).toEqual(3);
|
||||
|
@ -355,17 +356,17 @@ const DBC_FOUR_BIT_LE_SIGNAL = `
|
|||
BO_ 768 NEW_MSG_1: 8 XXX
|
||||
SG_ NEW_SIGNAL_1 : 6|4@1+ (1,0) [0|15] "" XXX
|
||||
`;
|
||||
test("int32 parser produces correct value for 4-bit little endian signal", () => {
|
||||
test('int32 parser produces correct value for 4-bit little endian signal', () => {
|
||||
const dbc = new DBC(DBC_FOUR_BIT_LE_SIGNAL);
|
||||
const signalSpec = dbc.getMessageFrame(768).signals["NEW_SIGNAL_1"];
|
||||
const signalSpec = dbc.getMessageFrame(768).signals.NEW_SIGNAL_1;
|
||||
|
||||
// this data is symmetric, the data bits are 1111
|
||||
const hexDataSymmetric = "f00f000000000000";
|
||||
const hexDataSymmetric = 'f00f000000000000';
|
||||
const symValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSymmetric, 8);
|
||||
expect(symValue).toEqual(15);
|
||||
|
||||
// this data is asymmetric, the data bits are 1101
|
||||
const hexDataAsymmetric = "f002000000000000";
|
||||
const hexDataAsymmetric = 'f002000000000000';
|
||||
const aSymValue = dbcInt32SignalValue(dbc, signalSpec, hexDataAsymmetric, 8);
|
||||
expect(aSymValue).toEqual(11);
|
||||
});
|
||||
|
@ -385,12 +386,12 @@ BO_ 1265 CLU11: 4 CLU
|
|||
SG_ CF_Clu_AmpInfo : 25|1@1+ (1.0,0.0) [0.0|1.0] "" BCM
|
||||
SG_ CF_Clu_AliveCnt1 : 28|4@1+ (1.0,0.0) [0.0|15.0] "" AHLS,EMS,EPB,LDWS_LKAS,MDPS,SCC
|
||||
`;
|
||||
test("int32 parser produces correct value for 4-bit little endian signal within a 4-byte message", () => {
|
||||
test('int32 parser produces correct value for 4-bit little endian signal within a 4-byte message', () => {
|
||||
const dbc = new DBC(DBC_FOUR_BIT_LE_SIGNAL_FOUR_BYTE_MESSAGE);
|
||||
const frame = dbc.getMessageFrame(1265);
|
||||
const signalSpec = frame.signals["CF_Clu_AliveCnt1"];
|
||||
const signalSpec = frame.signals.CF_Clu_AliveCnt1;
|
||||
|
||||
const hexData = "2000662000000000";
|
||||
const hexData = '2000662000000000';
|
||||
const value = dbcInt32SignalValue(dbc, signalSpec, hexData, frame.size);
|
||||
expect(value).toEqual(2);
|
||||
});
|
||||
|
@ -403,16 +404,16 @@ BO_ 688 SAS11: 5 MDPS
|
|||
SG_ MsgCount : 32|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS
|
||||
SG_ CheckSum : 36|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS
|
||||
`;
|
||||
test("int32 parser produces correct value for 2-byte signed little endian signal within a 5-byte message", () => {
|
||||
test('int32 parser produces correct value for 2-byte signed little endian signal within a 5-byte message', () => {
|
||||
const dbc = new DBC(DBC_MESSAGE_WITH_LE_SIGNED_SIGNAL);
|
||||
const frame = dbc.getMessageFrame(688);
|
||||
const signalSpec = frame.signals["SAS_Angle"];
|
||||
const signalSpec = frame.signals.SAS_Angle;
|
||||
|
||||
const hexData = "000000fafe000700";
|
||||
const hexData = '000000fafe000700';
|
||||
const value = dbcInt32SignalValue(dbc, signalSpec, hexData, frame.size);
|
||||
expect(value).toEqual(0.0);
|
||||
|
||||
const hexData2 = "0b000907d8b30000";
|
||||
const hexData2 = '0b000907d8b30000';
|
||||
const value2 = dbcInt32SignalValue(dbc, signalSpec, hexData2, frame.size);
|
||||
expect(value2).toEqual(1.1);
|
||||
});
|
||||
|
@ -424,12 +425,12 @@ BO_ 37 STEERING_CONTROL: 8 XXX
|
|||
CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180";
|
||||
`;
|
||||
|
||||
test("dbc parser parses top-level comment with chffr metric", () => {
|
||||
test('dbc parser parses top-level comment with chffr metric', () => {
|
||||
const dbc = new DBC(DBC_CHFFR_METRIC_COMMENT);
|
||||
const { comments } = dbc;
|
||||
|
||||
expect(comments.length).toEqual(1);
|
||||
expect(comments[0]).toEqual(
|
||||
"CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180"
|
||||
'CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180'
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import DBC, { swapOrder } from "../../models/can/dbc";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import DBC, { swapOrder } from '../../models/can/dbc';
|
||||
|
||||
const ACURA_DBC = fs.readFileSync("src/__tests__/res/acura.dbc", "utf-8");
|
||||
//import { TESLA_DBC } from "../res/tesla.dbc";
|
||||
const ACURA_DBC = fs.readFileSync('src/__tests__/res/acura.dbc', 'utf-8');
|
||||
// import { TESLA_DBC } from "../res/tesla.dbc";
|
||||
|
||||
test("DBC.text() for acura DBC should be equivalent to its original text", () => {
|
||||
test('DBC.text() for acura DBC should be equivalent to its original text', () => {
|
||||
const dbc = new DBC(ACURA_DBC);
|
||||
|
||||
expect(dbc.text()).toBe(ACURA_DBC);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Entries from "../../models/can/entries";
|
||||
import Entries from '../../models/can/entries';
|
||||
|
||||
test("segment index low is inclusive and index high is exclusive", () => {
|
||||
test('segment index low is inclusive and index high is exclusive', () => {
|
||||
const entries = [
|
||||
{ time: 1.0 },
|
||||
{ time: 3.45 },
|
||||
|
@ -16,8 +16,8 @@ test("segment index low is inclusive and index high is exclusive", () => {
|
|||
expect(segmentIdxHi).toBe(entries.length - 1);
|
||||
});
|
||||
|
||||
test("segment index cant return negative indexes", () => {
|
||||
var indices = Entries.findSegmentIndices([], [123, 321], true);
|
||||
test('segment index cant return negative indexes', () => {
|
||||
const indices = Entries.findSegmentIndices([], [123, 321], true);
|
||||
expect(indices[0]).toBe(0);
|
||||
expect(indices[1]).toBe(0);
|
||||
});
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import Frame from "../../models/can/frame";
|
||||
import Frame from '../../models/can/frame';
|
||||
|
||||
const FRAME_HEADER = "BO_ 255 SOME_FRAME: 5 ADAS";
|
||||
const FRAME_HEADER = 'BO_ 255 SOME_FRAME: 5 ADAS';
|
||||
|
||||
test("Frame.header() returns spec compliant representation", () => {
|
||||
test('Frame.header() returns spec compliant representation', () => {
|
||||
const frame = new Frame({
|
||||
name: "SOME_FRAME",
|
||||
name: 'SOME_FRAME',
|
||||
id: 255,
|
||||
size: 5,
|
||||
transmitters: ["ADAS"]
|
||||
transmitters: ['ADAS']
|
||||
});
|
||||
expect(frame.header()).toEqual(FRAME_HEADER);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Signal from "../../models/can/signal";
|
||||
import Signal from '../../models/can/signal';
|
||||
|
||||
const someSignalParams = {
|
||||
name: "STEER_TORQUE",
|
||||
name: 'STEER_TORQUE',
|
||||
startBit: 7,
|
||||
size: 16,
|
||||
isLittleEndian: false,
|
||||
|
@ -10,11 +10,11 @@ const someSignalParams = {
|
|||
offset: 0,
|
||||
min: -3840,
|
||||
max: 3840,
|
||||
unit: ""
|
||||
unit: ''
|
||||
};
|
||||
|
||||
const someOtherSignalParams = {
|
||||
name: "DIFFERENT_NAME",
|
||||
name: 'DIFFERENT_NAME',
|
||||
startBit: 0,
|
||||
size: 16,
|
||||
isLittleEndian: false,
|
||||
|
@ -23,24 +23,24 @@ const someOtherSignalParams = {
|
|||
offset: 0,
|
||||
min: -3840,
|
||||
max: 3840,
|
||||
unit: ""
|
||||
unit: ''
|
||||
};
|
||||
|
||||
test("Signal.equals returns true for signals with identical properties", () => {
|
||||
test('Signal.equals returns true for signals with identical properties', () => {
|
||||
const someSignal = new Signal(someSignalParams);
|
||||
const someEquivalentSignal = new Signal(someSignalParams);
|
||||
expect(someSignal.equals(someEquivalentSignal)).toBe(true);
|
||||
});
|
||||
|
||||
test("Signal.equals returns false for signals with different properties", () => {
|
||||
test('Signal.equals returns false for signals with different properties', () => {
|
||||
const someSignal = new Signal(someSignalParams);
|
||||
const differentSignal = new Signal(someOtherSignalParams);
|
||||
expect(someSignal.equals(differentSignal)).toBe(false);
|
||||
});
|
||||
|
||||
test("Signal.bitDescription returns proper description for a little endian signal", () => {
|
||||
test('Signal.bitDescription returns proper description for a little endian signal', () => {
|
||||
const littleEndianSignal = new Signal({
|
||||
name: "little endian signal",
|
||||
name: 'little endian signal',
|
||||
startBit: 20,
|
||||
size: 4,
|
||||
isLittleEndian: true
|
||||
|
@ -52,9 +52,9 @@ test("Signal.bitDescription returns proper description for a little endian signa
|
|||
expect(littleEndianSignal.bitDescription(23).bitNumber).toBe(3);
|
||||
});
|
||||
|
||||
test("Signal.bitDescription returns proper description for a big endian signal", () => {
|
||||
test('Signal.bitDescription returns proper description for a big endian signal', () => {
|
||||
const bigEndianSignal = new Signal({
|
||||
name: "big endian signal",
|
||||
name: 'big endian signal',
|
||||
startBit: 7,
|
||||
size: 16,
|
||||
isLittleEndian: false
|
||||
|
@ -91,9 +91,9 @@ test("Signal.bitDescription returns proper description for a big endian signal",
|
|||
expect(bigEndianSignal.bitDescription(7)).toEqual(bitSevenDescription);
|
||||
});
|
||||
|
||||
test("Signal.bitDescription returns null for bit index that is not in its range", () => {
|
||||
test('Signal.bitDescription returns null for bit index that is not in its range', () => {
|
||||
const someSignal = new Signal({
|
||||
name: "some signal",
|
||||
name: 'some signal',
|
||||
startBit: 20,
|
||||
size: 4,
|
||||
isLittleEndian: false
|
||||
|
|
|
@ -5,10 +5,10 @@ note: 'right' and 'left' in test descriptions
|
|||
refer to the sides of the bit matrix
|
||||
as displayed to the user.
|
||||
*/
|
||||
import AddSignals from "../../components/AddSignals";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import { StyleSheetTestUtils } from "aphrodite";
|
||||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import { StyleSheetTestUtils } from 'aphrodite';
|
||||
import AddSignals from '../../components/AddSignals';
|
||||
|
||||
// Prevents style injection from firing after test finishes
|
||||
// and jsdom is torn down.
|
||||
|
@ -31,7 +31,7 @@ function createAddSignals(signals) {
|
|||
entries: [
|
||||
{
|
||||
relTime: 0,
|
||||
hexData: "0000000000000000"
|
||||
hexData: '0000000000000000'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -46,99 +46,99 @@ function createAddSignals(signals) {
|
|||
|
||||
return component;
|
||||
}
|
||||
test("double clicking adds a signal", () => {
|
||||
test('double clicking adds a signal', () => {
|
||||
const component = createAddSignals();
|
||||
|
||||
const firstBit = component.find(".bit").first();
|
||||
const firstBit = component.find('.bit').first();
|
||||
|
||||
firstBit.simulate("dblclick");
|
||||
const newSignal = Object.values(component.state("signals"))[0];
|
||||
firstBit.simulate('dblclick');
|
||||
const newSignal = Object.values(component.state('signals'))[0];
|
||||
|
||||
expect(newSignal).toBeDefined();
|
||||
expect(newSignal.size).toBe(1);
|
||||
});
|
||||
|
||||
test("dragging right to left across a byte creates a little endian signal", () => {
|
||||
test('dragging right to left across a byte creates a little endian signal', () => {
|
||||
const component = createAddSignals();
|
||||
const leftBitInByte = component.find(".bit").first();
|
||||
const rightBitInByte = component.find(".bit").at(7);
|
||||
rightBitInByte.simulate("mousedown");
|
||||
leftBitInByte.simulate("mouseup");
|
||||
const leftBitInByte = component.find('.bit').first();
|
||||
const rightBitInByte = component.find('.bit').at(7);
|
||||
rightBitInByte.simulate('mousedown');
|
||||
leftBitInByte.simulate('mouseup');
|
||||
|
||||
const newSignal = Object.values(component.state("signals"))[0];
|
||||
const newSignal = Object.values(component.state('signals'))[0];
|
||||
expect(newSignal).toBeDefined();
|
||||
expect(newSignal.size).toBe(8);
|
||||
expect(newSignal.isLittleEndian).toBe(true);
|
||||
expect(newSignal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test("dragging left to right across a byte creates a big endian signal", () => {
|
||||
test('dragging left to right across a byte creates a big endian signal', () => {
|
||||
const component = createAddSignals();
|
||||
const leftBitInByte = component.find(".bit").first();
|
||||
const rightBitInByte = component.find(".bit").at(7);
|
||||
leftBitInByte.simulate("mousedown");
|
||||
rightBitInByte.simulate("mouseup");
|
||||
const leftBitInByte = component.find('.bit').first();
|
||||
const rightBitInByte = component.find('.bit').at(7);
|
||||
leftBitInByte.simulate('mousedown');
|
||||
rightBitInByte.simulate('mouseup');
|
||||
|
||||
const newSignal = Object.values(component.state("signals"))[0];
|
||||
const newSignal = Object.values(component.state('signals'))[0];
|
||||
expect(newSignal).toBeDefined();
|
||||
expect(newSignal.size).toBe(8);
|
||||
expect(newSignal.isLittleEndian).toBe(false);
|
||||
expect(newSignal.startBit).toBe(7);
|
||||
});
|
||||
|
||||
test("dragging from the left of byte 0 to right of byte 1 creates a big endian signal spanning both bytes", () => {
|
||||
test('dragging from the left of byte 0 to right of byte 1 creates a big endian signal spanning both bytes', () => {
|
||||
const component = createAddSignals();
|
||||
const leftBitInByte = component.find(".bit").first();
|
||||
const rightBitInByte = component.find(".bit").at(15);
|
||||
leftBitInByte.simulate("mousedown");
|
||||
rightBitInByte.simulate("mouseup");
|
||||
const leftBitInByte = component.find('.bit').first();
|
||||
const rightBitInByte = component.find('.bit').at(15);
|
||||
leftBitInByte.simulate('mousedown');
|
||||
rightBitInByte.simulate('mouseup');
|
||||
|
||||
const newSignal = Object.values(component.state("signals"))[0];
|
||||
const newSignal = Object.values(component.state('signals'))[0];
|
||||
expect(newSignal).toBeDefined();
|
||||
expect(newSignal.size).toBe(16);
|
||||
expect(newSignal.isLittleEndian).toBe(false);
|
||||
expect(newSignal.startBit).toBe(7);
|
||||
});
|
||||
|
||||
test("dragging from the right of byte 0 to the left of byte 1 creates a little endian signal spanning both bytes", () => {
|
||||
test('dragging from the right of byte 0 to the left of byte 1 creates a little endian signal spanning both bytes', () => {
|
||||
const component = createAddSignals();
|
||||
const leftBitInByteOne = component.find(".bit").at(8); // left of byte 1
|
||||
const rightBitInByteZero = component.find(".bit").at(7); // right of byte 0
|
||||
const leftBitInByteOne = component.find('.bit').at(8); // left of byte 1
|
||||
const rightBitInByteZero = component.find('.bit').at(7); // right of byte 0
|
||||
|
||||
rightBitInByteZero.simulate("mousedown");
|
||||
leftBitInByteOne.simulate("mouseup");
|
||||
rightBitInByteZero.simulate('mousedown');
|
||||
leftBitInByteOne.simulate('mouseup');
|
||||
|
||||
const newSignal = Object.values(component.state("signals"))[0];
|
||||
const newSignal = Object.values(component.state('signals'))[0];
|
||||
expect(newSignal).toBeDefined();
|
||||
expect(newSignal.size).toBe(16);
|
||||
expect(newSignal.isLittleEndian).toBe(true);
|
||||
expect(newSignal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test("dragging from the left of byte 1 to the right of byte 0 creates a little endian signal spanning both bytes", () => {
|
||||
test('dragging from the left of byte 1 to the right of byte 0 creates a little endian signal spanning both bytes', () => {
|
||||
const component = createAddSignals();
|
||||
const leftBitInByteOne = component.find(".bit").at(8);
|
||||
const rightBitInByteZero = component.find(".bit").at(7);
|
||||
const leftBitInByteOne = component.find('.bit').at(8);
|
||||
const rightBitInByteZero = component.find('.bit').at(7);
|
||||
|
||||
leftBitInByteOne.simulate("mousedown");
|
||||
rightBitInByteZero.simulate("mouseup");
|
||||
leftBitInByteOne.simulate('mousedown');
|
||||
rightBitInByteZero.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(16);
|
||||
expect(signal.isLittleEndian).toBe(true);
|
||||
expect(signal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test("dragging from the right of byte 1 to the left of byte 0 creates a big endian signal spanning both bytes", () => {
|
||||
test('dragging from the right of byte 1 to the left of byte 0 creates a big endian signal spanning both bytes', () => {
|
||||
const component = createAddSignals();
|
||||
const leftBitInByteZero = component.find(".bit").at(0);
|
||||
const rightBitInByteOne = component.find(".bit").at(15);
|
||||
const leftBitInByteZero = component.find('.bit').at(0);
|
||||
const rightBitInByteOne = component.find('.bit').at(15);
|
||||
|
||||
rightBitInByteOne.simulate("mousedown");
|
||||
leftBitInByteZero.simulate("mouseup");
|
||||
rightBitInByteOne.simulate('mousedown');
|
||||
leftBitInByteZero.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(16);
|
||||
expect(signal.isLittleEndian).toBe(false);
|
||||
|
@ -147,205 +147,205 @@ test("dragging from the right of byte 1 to the left of byte 0 creates a big endi
|
|||
|
||||
// signal mutation
|
||||
|
||||
test.skip("dragging a one-bit big-endian signal to the right should extend it to the right of the byte", () => {
|
||||
test.skip('dragging a one-bit big-endian signal to the right should extend it to the right of the byte', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 7, size: 1, isLittleEndian: false });
|
||||
|
||||
const signalBit = component.find(".bit").at(0);
|
||||
signalBit.simulate("mousedown");
|
||||
const signalBit = component.find('.bit').at(0);
|
||||
signalBit.simulate('mousedown');
|
||||
for (let i = 1; i < 8; i++) {
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(i)
|
||||
.simulate("mouseenter");
|
||||
.simulate('mouseenter');
|
||||
}
|
||||
const bitAtRightOfFirstByte = component.find(".bit").at(7);
|
||||
bitAtRightOfFirstByte.simulate("mouseup");
|
||||
const bitAtRightOfFirstByte = component.find('.bit').at(7);
|
||||
bitAtRightOfFirstByte.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(false);
|
||||
expect(signal.startBit).toBe(7);
|
||||
});
|
||||
|
||||
test.skip("dragging a one-bit little-endian signal to the right should extend it to the right of the byte", () => {
|
||||
test.skip('dragging a one-bit little-endian signal to the right should extend it to the right of the byte', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 7, size: 1, isLittleEndian: true });
|
||||
|
||||
const signalBit = component.find(".bit").at(0);
|
||||
signalBit.simulate("mousedown");
|
||||
const signalBit = component.find('.bit').at(0);
|
||||
signalBit.simulate('mousedown');
|
||||
for (let i = 1; i < 8; i++) {
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(i)
|
||||
.simulate("mouseenter");
|
||||
.simulate('mouseenter');
|
||||
}
|
||||
const bitAtRightOfFirstByte = component.find(".bit").at(7);
|
||||
bitAtRightOfFirstByte.simulate("mouseup");
|
||||
const bitAtRightOfFirstByte = component.find('.bit').at(7);
|
||||
bitAtRightOfFirstByte.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(true);
|
||||
expect(signal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test.skip("dragging a one-bit big-endian signal to the left should extend it to the left of the byte", () => {
|
||||
test.skip('dragging a one-bit big-endian signal to the left should extend it to the left of the byte', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 0, size: 1, isLittleEndian: false });
|
||||
|
||||
const signalBit = component.find(".bit").at(7);
|
||||
signalBit.simulate("mousedown");
|
||||
const signalBit = component.find('.bit').at(7);
|
||||
signalBit.simulate('mousedown');
|
||||
for (let i = 6; i > -1; i--) {
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(i)
|
||||
.simulate("mouseenter");
|
||||
.simulate('mouseenter');
|
||||
}
|
||||
const bitAtRightOfFirstByte = component.find(".bit").at(0);
|
||||
bitAtRightOfFirstByte.simulate("mouseup");
|
||||
const bitAtRightOfFirstByte = component.find('.bit').at(0);
|
||||
bitAtRightOfFirstByte.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(false);
|
||||
expect(signal.startBit).toBe(7);
|
||||
});
|
||||
|
||||
test.skip("extending a two-bit big-endian signal by its LSB should extend it to the right of the byte", () => {
|
||||
test.skip('extending a two-bit big-endian signal by its LSB should extend it to the right of the byte', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 7, size: 2, isLittleEndian: false });
|
||||
|
||||
const lsb = component.find(".bit").at(1);
|
||||
lsb.simulate("mousedown");
|
||||
const lsb = component.find('.bit').at(1);
|
||||
lsb.simulate('mousedown');
|
||||
for (let i = 0; i < 8; i++) {
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(i)
|
||||
.simulate("mouseenter");
|
||||
.simulate('mouseenter');
|
||||
}
|
||||
const bitAtRightOfFirstByte = component.find(".bit").at(7);
|
||||
bitAtRightOfFirstByte.simulate("mouseup");
|
||||
const bitAtRightOfFirstByte = component.find('.bit').at(7);
|
||||
bitAtRightOfFirstByte.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(false);
|
||||
expect(signal.startBit).toBe(7);
|
||||
});
|
||||
|
||||
test.skip("a two-bit little-endian signal should extend by its LSB to the end of the byte", () => {
|
||||
test.skip('a two-bit little-endian signal should extend by its LSB to the end of the byte', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 6, size: 2, isLittleEndian: true });
|
||||
|
||||
const lsb = component.find(".bit").at(1);
|
||||
lsb.simulate("mousedown");
|
||||
const lsb = component.find('.bit').at(1);
|
||||
lsb.simulate('mousedown');
|
||||
for (let i = 0; i < 8; i++) {
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(i)
|
||||
.simulate("mouseenter");
|
||||
.simulate('mouseenter');
|
||||
}
|
||||
const bitAtRightOfFirstByte = component.find(".bit").at(7);
|
||||
bitAtRightOfFirstByte.simulate("mouseup");
|
||||
const bitAtRightOfFirstByte = component.find('.bit').at(7);
|
||||
bitAtRightOfFirstByte.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(true);
|
||||
expect(signal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test("dragging the lsb of a little-endian signal spanning an entire byte should not be allowed to pass the MSB", () => {
|
||||
test('dragging the lsb of a little-endian signal spanning an entire byte should not be allowed to pass the MSB', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 0, size: 8, isLittleEndian: true });
|
||||
|
||||
const lsb = component.find(".bit").at(7);
|
||||
lsb.simulate("mousedown");
|
||||
const lsb = component.find('.bit').at(7);
|
||||
lsb.simulate('mousedown');
|
||||
|
||||
const bitPastMsb = component.find(".bit").at(15);
|
||||
bitPastMsb.simulate("mouseenter");
|
||||
bitPastMsb.simulate("mouseup");
|
||||
const bitPastMsb = component.find('.bit').at(15);
|
||||
bitPastMsb.simulate('mouseenter');
|
||||
bitPastMsb.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(true);
|
||||
expect(signal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test.skip("dragging the lsb of a big-endian signal towards the msb in the same byte should contract the signal", () => {
|
||||
test.skip('dragging the lsb of a big-endian signal towards the msb in the same byte should contract the signal', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 7, size: 8, isLittleEndian: false });
|
||||
|
||||
const lsb = component.find(".bit").at(7);
|
||||
lsb.simulate("mousedown");
|
||||
const lsb = component.find('.bit').at(7);
|
||||
lsb.simulate('mousedown');
|
||||
for (let i = 6; i > 0; i--) {
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(i)
|
||||
.simulate("mouseenter");
|
||||
.simulate('mouseenter');
|
||||
}
|
||||
component
|
||||
.find(".bit")
|
||||
.find('.bit')
|
||||
.at(1)
|
||||
.simulate("mouseup");
|
||||
.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(2);
|
||||
expect(signal.isLittleEndian).toBe(false);
|
||||
expect(signal.startBit).toBe(7);
|
||||
});
|
||||
|
||||
test("a big endian signal spanning one byte should switch to little endian preserving its bit coverage", () => {
|
||||
test('a big endian signal spanning one byte should switch to little endian preserving its bit coverage', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 0, size: 8, isLittleEndian: true });
|
||||
|
||||
const lsb = component.find(".bit").at(7);
|
||||
lsb.simulate("mousedown");
|
||||
const lsb = component.find('.bit').at(7);
|
||||
lsb.simulate('mousedown');
|
||||
|
||||
const bitPastMsb = component.find(".bit").at(15);
|
||||
bitPastMsb.simulate("mouseenter");
|
||||
bitPastMsb.simulate("mouseup");
|
||||
const bitPastMsb = component.find('.bit').at(15);
|
||||
bitPastMsb.simulate('mouseenter');
|
||||
bitPastMsb.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(8);
|
||||
expect(signal.isLittleEndian).toBe(true);
|
||||
expect(signal.startBit).toBe(0);
|
||||
});
|
||||
|
||||
test("dragging the msb of a 2-bit little endian signal to a lower byte should not change the signal", () => {
|
||||
test('dragging the msb of a 2-bit little endian signal to a lower byte should not change the signal', () => {
|
||||
const component = createAddSignals();
|
||||
component
|
||||
.instance()
|
||||
.createSignal({ startBit: 14, size: 2, isLittleEndian: true });
|
||||
|
||||
const msb = component.find(".bit").at(8);
|
||||
msb.simulate("mousedown");
|
||||
const bitOutOfBounds = component.find(".bit").at(0);
|
||||
bitOutOfBounds.simulate("mouseenter");
|
||||
bitOutOfBounds.simulate("mouseup");
|
||||
const msb = component.find('.bit').at(8);
|
||||
msb.simulate('mousedown');
|
||||
const bitOutOfBounds = component.find('.bit').at(0);
|
||||
bitOutOfBounds.simulate('mouseenter');
|
||||
bitOutOfBounds.simulate('mouseup');
|
||||
|
||||
const signal = Object.values(component.state("signals"))[0];
|
||||
const signal = Object.values(component.state('signals'))[0];
|
||||
expect(signal).toBeDefined();
|
||||
expect(signal.size).toBe(2);
|
||||
expect(signal.isLittleEndian).toBe(true);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
global.__JEST__ = 1;
|
||||
import CanExplorer from "../../CanExplorer";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import { StyleSheetTestUtils } from "aphrodite";
|
||||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import { StyleSheetTestUtils } from 'aphrodite';
|
||||
import CanExplorer from '../../CanExplorer';
|
||||
|
||||
test("CanExplorer renders", () => {
|
||||
global.__JEST__ = 1;
|
||||
|
||||
test('CanExplorer renders', () => {
|
||||
const canExplorer = shallow(<CanExplorer />);
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import CanGraph from '../../components/CanGraph';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import CanGraph from "../../components/CanGraph";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("CanGraph successfully mounts with minimal default props", () => {
|
||||
test('CanGraph successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<CanGraph
|
||||
onGraphRefAvailable={() => {}}
|
||||
|
@ -24,7 +24,7 @@ test("CanGraph successfully mounts with minimal default props", () => {
|
|||
dragPos={null}
|
||||
canReceiveGraphDrop={false}
|
||||
plottedSignals={[]}
|
||||
live={true}
|
||||
live
|
||||
/>
|
||||
);
|
||||
expect(component.exists()).toBe(true);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import CanGraphList from '../../components/CanGraphList';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import CanGraphList from "../../components/CanGraphList";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("CanGraphList successfully mounts with minimal default props", () => {
|
||||
test('CanGraphList successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<CanGraphList
|
||||
plottedSignals={[]}
|
||||
|
@ -16,7 +16,7 @@ test("CanGraphList successfully mounts with minimal default props", () => {
|
|||
onSignalUnplotPressed={() => {}}
|
||||
segment={[]}
|
||||
mergePlots={() => {}}
|
||||
live={true}
|
||||
live
|
||||
/>
|
||||
);
|
||||
expect(component.exists()).toBe(true);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import CanLog from '../../components/CanLog';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import CanLog from "../../components/CanLog";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("CanLog successfully mounts with minimal default props", () => {
|
||||
test('CanLog successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<CanLog
|
||||
message={null}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import DbcUpload from '../../components/DbcUpload';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import DbcUpload from "../../components/DbcUpload";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("DbcUpload successfully mounts with minimal default props", () => {
|
||||
test('DbcUpload successfully mounts with minimal default props', () => {
|
||||
const component = shallow(<DbcUpload />);
|
||||
expect(component.exists()).toBe(true);
|
||||
});
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import EditMessageModal from '../../components/EditMessageModal';
|
||||
import DbcUtils from '../../utils/dbc';
|
||||
import DBC from '../../models/can/dbc';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import EditMessageModal from "../../components/EditMessageModal";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import DbcUtils from "../../utils/dbc";
|
||||
import DBC from "../../models/can/dbc";
|
||||
|
||||
test("EditMessageModal successfully mounts with minimal default props", () => {
|
||||
test('EditMessageModal successfully mounts with minimal default props', () => {
|
||||
const dbc = new DBC();
|
||||
const frame = dbc.createFrame(0);
|
||||
const message = DbcUtils.createMessageSpec(dbc, 0, "0", 1);
|
||||
const message = DbcUtils.createMessageSpec(dbc, 0, '0', 1);
|
||||
|
||||
const component = shallow(
|
||||
<EditMessageModal
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React from 'react';
|
||||
import Moment from 'moment';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import Explorer from '../../components/Explorer';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import Explorer from "../../components/Explorer";
|
||||
import React from "react";
|
||||
import Moment from "moment";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("Explorer successfully mounts with minimal default props", () => {
|
||||
test('Explorer successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<Explorer
|
||||
url={null}
|
||||
live={true}
|
||||
live
|
||||
messages={{}}
|
||||
selectedMessage={null}
|
||||
onConfirmedSignalChange={() => {}}
|
||||
|
@ -21,7 +21,7 @@ test("Explorer successfully mounts with minimal default props", () => {
|
|||
seekIndex={0}
|
||||
currentParts={[0, 0]}
|
||||
partsLoaded={0}
|
||||
autoplay={true}
|
||||
autoplay
|
||||
showEditMessageModal={() => {}}
|
||||
onPartChange={() => {}}
|
||||
routeStartTime={Moment()}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import GithubDbcList from '../../components/GithubDbcList';
|
||||
|
||||
import OpenDbc from '../../api/OpenDbc';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import GithubDbcList from "../../components/GithubDbcList";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
import OpenDbc from "../../api/OpenDbc";
|
||||
|
||||
test("GithubDbcList successfully mounts with minimal default props", () => {
|
||||
test('GithubDbcList successfully mounts with minimal default props', () => {
|
||||
const openDbcClient = new OpenDbc(null);
|
||||
|
||||
const component = shallow(
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import HLS from "../../components/HLS";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import HLS from '../../components/HLS';
|
||||
|
||||
test("HLS successfully mounts with minimal default props", () => {
|
||||
test('HLS successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<HLS
|
||||
source={"http://comma.ai"}
|
||||
source="http://comma.ai"
|
||||
startTime={0}
|
||||
playbackSpeed={1}
|
||||
onVideoElementAvailable={() => {}}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
|
||||
import LoadDbcModal from '../../components/LoadDbcModal';
|
||||
import OpenDbc from '../../api/OpenDbc';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
import LoadDbcModal from "../../components/LoadDbcModal";
|
||||
import OpenDbc from "../../api/OpenDbc";
|
||||
|
||||
test("LoadDbcModal successfully mounts with minimal default props", () => {
|
||||
test('LoadDbcModal successfully mounts with minimal default props', () => {
|
||||
const openDbcClient = new OpenDbc(null);
|
||||
const component = shallow(
|
||||
<LoadDbcModal
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import LoadingBar from "../../components/LoadingBar";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import LoadingBar from '../../components/LoadingBar';
|
||||
|
||||
test("LoadingBar successfully mounts with minimal default props", () => {
|
||||
test('LoadingBar successfully mounts with minimal default props', () => {
|
||||
const component = shallow(<LoadingBar />);
|
||||
expect(component.exists()).toBe(true);
|
||||
});
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
|
||||
import MessageBytes from '../../components/MessageBytes';
|
||||
import DbcUtils from '../../utils/dbc';
|
||||
import DBC from '../../models/can/dbc';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
import MessageBytes from "../../components/MessageBytes";
|
||||
import DbcUtils from "../../utils/dbc";
|
||||
import DBC from "../../models/can/dbc";
|
||||
|
||||
test("MessageBytes successfully mounts with minimal default props", () => {
|
||||
const message = DbcUtils.createMessageSpec(new DBC(), 0, "0", 1);
|
||||
test('MessageBytes successfully mounts with minimal default props', () => {
|
||||
const message = DbcUtils.createMessageSpec(new DBC(), 0, '0', 1);
|
||||
const component = shallow(
|
||||
<MessageBytes seekTime={0} message={message} live={true} />
|
||||
<MessageBytes seekTime={0} message={message} live />
|
||||
);
|
||||
expect(component.exists()).toBe(true);
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import Meta from '../../components/Meta';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import Meta from "../../components/Meta";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("Meta successfully mounts with minimal default props", () => {
|
||||
test('Meta successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<Meta
|
||||
url={null}
|
||||
|
@ -26,7 +26,7 @@ test("Meta successfully mounts with minimal default props", () => {
|
|||
seekIndex={0}
|
||||
maxByteStateChangeCount={0}
|
||||
isDemo={false}
|
||||
live={true}
|
||||
live
|
||||
/>
|
||||
);
|
||||
expect(component.exists()).toBe(true);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import PartSelector from '../../components/PartSelector';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import PartSelector from "../../components/PartSelector";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("PartSelector successfully mounts with minimal default props", () => {
|
||||
test('PartSelector successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<PartSelector onPartChange={() => {}} partsCount={0} selectedPart={0} />
|
||||
);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import PlayButton from '../../components/PlayButton';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import PlayButton from "../../components/PlayButton";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("PlayButton successfully mounts with minimal default props", () => {
|
||||
test('PlayButton successfully mounts with minimal default props', () => {
|
||||
const component = shallow(<PlayButton />);
|
||||
expect(component.exists()).toBe(true);
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import RouteSeeker from '../../components/RouteSeeker';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import RouteSeeker from "../../components/RouteSeeker";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("RouteSeeker successfully mounts with minimal default props", () => {
|
||||
test('RouteSeeker successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<RouteSeeker
|
||||
nearestFrameTime={0}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
global.__JEST__ = 1;
|
||||
import API from '@commaai/comma-api';
|
||||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import { StyleSheetTestUtils } from 'aphrodite';
|
||||
import RouteVideoSync from '../../components/RouteVideoSync';
|
||||
|
||||
import API from "@commaai/comma-api";
|
||||
import RouteVideoSync from "../../components/RouteVideoSync";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import { StyleSheetTestUtils } from "aphrodite";
|
||||
global.__JEST__ = 1;
|
||||
|
||||
// Prevents style injection from firing after test finishes
|
||||
// and jsdom is torn down.
|
||||
|
@ -15,7 +15,7 @@ afterEach(() => {
|
|||
StyleSheetTestUtils.clearBufferAndResumeStyleInjection();
|
||||
});
|
||||
|
||||
test("RouteVideoSync successfully mounts with minimal default props", () => {
|
||||
test('RouteVideoSync successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<RouteVideoSync
|
||||
message={null}
|
||||
|
@ -26,7 +26,7 @@ test("RouteVideoSync successfully mounts with minimal default props", () => {
|
|||
userSeekIndex={0}
|
||||
playing={false}
|
||||
playSpeed={1}
|
||||
url={"http://comma.ai"}
|
||||
url="http://comma.ai"
|
||||
canFrameOffset={0}
|
||||
firstCanTime={0}
|
||||
onVideoClick={() => {}}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
|
||||
import SaveDbcModal from '../../components/SaveDbcModal';
|
||||
import OpenDbc from '../../api/OpenDbc';
|
||||
import DBC from '../../models/can/dbc';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
import SaveDbcModal from "../../components/SaveDbcModal";
|
||||
import OpenDbc from "../../api/OpenDbc";
|
||||
import DBC from "../../models/can/dbc";
|
||||
|
||||
test("SaveDbcModal successfully mounts with minimal default props", () => {
|
||||
test('SaveDbcModal successfully mounts with minimal default props', () => {
|
||||
const openDbcClient = new OpenDbc(null);
|
||||
const dbc = new DBC();
|
||||
const component = shallow(
|
||||
<SaveDbcModal
|
||||
dbc={dbc}
|
||||
sourceDbcFilename={""}
|
||||
sourceDbcFilename=""
|
||||
onDbcSaved={() => {}}
|
||||
handleClose={() => {}}
|
||||
openDbcClient={openDbcClient}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import SignalLegend from '../../components/SignalLegend';
|
||||
|
||||
global.__JEST__ = 1;
|
||||
|
||||
import SignalLegend from "../../components/SignalLegend";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
|
||||
test("SignalLegend successfully mounts with minimal default props", () => {
|
||||
test('SignalLegend successfully mounts with minimal default props', () => {
|
||||
const component = shallow(
|
||||
<SignalLegend
|
||||
signals={{}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { shade } from "../../utils/color";
|
||||
import { shade } from '../../utils/color';
|
||||
|
||||
test("Shade darkens rgb white (255,255,255)", () => {
|
||||
test('Shade darkens rgb white (255,255,255)', () => {
|
||||
const rgb = [255, 255, 255];
|
||||
const darkenRgb = shade(rgb, -0.5);
|
||||
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
global.__JEST__ = 1;
|
||||
import extend from 'xtend';
|
||||
import DbcUtils from '../../utils/dbc';
|
||||
import DBC from '../../models/can/dbc';
|
||||
import Signal from '../../models/can/signal';
|
||||
|
||||
import DbcUtils from "../../utils/dbc";
|
||||
import DBC from "../../models/can/dbc";
|
||||
import Signal from "../../models/can/signal";
|
||||
import extend from "xtend";
|
||||
global.__JEST__ = 1;
|
||||
|
||||
// want to mock pandareader and test processStreamedCanMessages
|
||||
const SAMPLE_MESSAGE = {
|
||||
address: 0x10,
|
||||
busTime: 0,
|
||||
data: Buffer.from("abababababababab", "hex"),
|
||||
data: Buffer.from('abababababababab', 'hex'),
|
||||
bus: 1
|
||||
};
|
||||
const SAMPLE_MESSAGE_ID = "1:10";
|
||||
const SAMPLE_MESSAGE_ID = '1:10';
|
||||
|
||||
function expectSampleMessageFieldsPreserved(messages, frame) {
|
||||
const { address, busTime, data, bus } = SAMPLE_MESSAGE;
|
||||
const {
|
||||
address, busTime, data, bus
|
||||
} = SAMPLE_MESSAGE;
|
||||
expect(messages[SAMPLE_MESSAGE_ID].address).toEqual(address);
|
||||
expect(messages[SAMPLE_MESSAGE_ID].id).toEqual(SAMPLE_MESSAGE_ID);
|
||||
expect(messages[SAMPLE_MESSAGE_ID].bus).toEqual(bus);
|
||||
|
@ -28,7 +30,7 @@ function expectSampleMessageFieldsPreserved(messages, frame) {
|
|||
// function addCanMessage([address, busTime, data, bus], dbc, canStartTime, messages, prevMsgEntries, byteStateChangeCountsByMessage) {
|
||||
function addMessages(messages, message, dbc, n) {
|
||||
const firstCanTime = 0;
|
||||
let nextMessage = () => {
|
||||
const nextMessage = () => {
|
||||
message = extend(message);
|
||||
message.busTime += 1;
|
||||
return message;
|
||||
|
@ -38,7 +40,7 @@ function addMessages(messages, message, dbc, n) {
|
|||
DbcUtils.addCanMessage(nextMessage(), dbc, firstCanTime, messages, {}, {});
|
||||
}
|
||||
}
|
||||
test("addCanMessage should add raw can message with empty dbc", () => {
|
||||
test('addCanMessage should add raw can message with empty dbc', () => {
|
||||
const messages = {};
|
||||
addMessages(messages, SAMPLE_MESSAGE, new DBC(), 1);
|
||||
|
||||
|
@ -46,7 +48,7 @@ test("addCanMessage should add raw can message with empty dbc", () => {
|
|||
expectSampleMessageFieldsPreserved(messages);
|
||||
});
|
||||
|
||||
test("addCanMessage should add multiple raw can messages with empty dbc", () => {
|
||||
test('addCanMessage should add multiple raw can messages with empty dbc', () => {
|
||||
const messages = {};
|
||||
addMessages(messages, SAMPLE_MESSAGE, new DBC(), 3);
|
||||
|
||||
|
@ -54,12 +56,12 @@ test("addCanMessage should add multiple raw can messages with empty dbc", () =>
|
|||
expectSampleMessageFieldsPreserved(messages);
|
||||
});
|
||||
|
||||
test("addCanMessage should add parsed can message with dbc containing message spec", () => {
|
||||
test('addCanMessage should add parsed can message with dbc containing message spec', () => {
|
||||
const messages = {};
|
||||
// create dbc with message spec and signal for sample_message
|
||||
const dbc = new DBC();
|
||||
dbc.createFrame(SAMPLE_MESSAGE.address);
|
||||
const signal = new Signal({ name: "NEW_SIGNAL", startBit: 0, size: 8 });
|
||||
const signal = new Signal({ name: 'NEW_SIGNAL', startBit: 0, size: 8 });
|
||||
dbc.addSignal(SAMPLE_MESSAGE.address, signal);
|
||||
|
||||
// add 1 sample_message
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DBC from "./models/can/dbc";
|
||||
import DBC from './models/can/dbc';
|
||||
|
||||
const AcuraDbc = new DBC(`
|
||||
VERSION ""
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import GitHub from "github-api";
|
||||
import GitHub from 'github-api';
|
||||
|
||||
import { OPENDBC_SOURCE_REPO } from "../config";
|
||||
import { OPENDBC_SOURCE_REPO } from '../config';
|
||||
|
||||
export default class OpenDBC {
|
||||
constructor(token) {
|
||||
this.token = token;
|
||||
this.github = new GitHub({ token });
|
||||
this.sourceRepo = this.github.getRepo("commaai", "opendbc");
|
||||
this.sourceRepo = this.github.getRepo('commaai', 'opendbc');
|
||||
this.githubUsername = null;
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,10 @@ export default class OpenDBC {
|
|||
async getGithubUsername() {
|
||||
if (this.githubUsername) {
|
||||
return this.githubUsername;
|
||||
} else {
|
||||
const githubUsername = await this.fetchGithubUsername();
|
||||
if (githubUsername) {
|
||||
return githubUsername;
|
||||
}
|
||||
}
|
||||
const githubUsername = await this.fetchGithubUsername();
|
||||
if (githubUsername) {
|
||||
return githubUsername;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,13 +49,13 @@ export default class OpenDBC {
|
|||
if (repoFullName === undefined) {
|
||||
repo = this.sourceRepo;
|
||||
} else {
|
||||
const [username, repoName] = repoFullName.split("/");
|
||||
const [username, repoName] = repoFullName.split('/');
|
||||
repo = this.github.getRepo(username, repoName);
|
||||
}
|
||||
try {
|
||||
const response = await repo.getContents("master", "");
|
||||
const response = await repo.getContents('master', '');
|
||||
|
||||
return response.data.map(content => content.path);
|
||||
return response.data.map((content) => content.path);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
|
@ -67,15 +66,15 @@ export default class OpenDBC {
|
|||
if (repoFullName === undefined) {
|
||||
repo = this.sourceRepo;
|
||||
} else {
|
||||
const [username, repoName] = repoFullName.split("/");
|
||||
const [username, repoName] = repoFullName.split('/');
|
||||
repo = this.github.getRepo(username, repoName);
|
||||
}
|
||||
|
||||
const fileContents = await repo.getContents("master", dbcPath);
|
||||
const fileContents = await repo.getContents('master', dbcPath);
|
||||
|
||||
const rawContentsUrl = fileContents.data.download_url;
|
||||
|
||||
const resp = await fetch(rawContentsUrl, { cache: "no-cache" });
|
||||
const resp = await fetch(rawContentsUrl, { cache: 'no-cache' });
|
||||
|
||||
return resp.text();
|
||||
}
|
||||
|
@ -90,24 +89,22 @@ export default class OpenDBC {
|
|||
const githubUsername = await this.getGithubUsername();
|
||||
if (!githubUsername) return null;
|
||||
|
||||
const openDbcFork = this.github.getRepo(githubUsername, "opendbc");
|
||||
const openDbcFork = this.github.getRepo(githubUsername, 'opendbc');
|
||||
const repoDetailResp = await openDbcFork.getDetails();
|
||||
const repoDetails = repoDetailResp.data;
|
||||
|
||||
if (this.repoSourceIsOpenDbc(repoDetails)) {
|
||||
return repoDetails.full_name;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async fork() {
|
||||
const forkResponse = await this.sourceRepo.fork();
|
||||
if (forkResponse.status === 202) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async commitFile(repoFullName, path, contents, commitMessage) {
|
||||
|
@ -115,11 +112,11 @@ export default class OpenDBC {
|
|||
repo is of format username/reponame
|
||||
authenciated user must have write access to repo
|
||||
*/
|
||||
const [user, repoName] = repoFullName.split("/");
|
||||
const [user, repoName] = repoFullName.split('/');
|
||||
const repo = this.github.getRepo(user, repoName);
|
||||
|
||||
// get HEAD reference
|
||||
const refResp = await repo.getRef("heads/master");
|
||||
const refResp = await repo.getRef('heads/master');
|
||||
const ref = refResp.data;
|
||||
|
||||
// get HEAD commit sha
|
||||
|
@ -133,9 +130,9 @@ export default class OpenDBC {
|
|||
// create new tree
|
||||
const tree = [
|
||||
{
|
||||
mode: "100644",
|
||||
path: path,
|
||||
type: "blob",
|
||||
mode: '100644',
|
||||
path,
|
||||
type: 'blob',
|
||||
content: contents
|
||||
}
|
||||
];
|
||||
|
@ -147,13 +144,13 @@ export default class OpenDBC {
|
|||
const commitResp = await repo.commit(
|
||||
headCommit.sha,
|
||||
createdTree.sha,
|
||||
commitMessage || "OpenDBC updates"
|
||||
commitMessage || 'OpenDBC updates'
|
||||
);
|
||||
const commit = commitResp.data;
|
||||
|
||||
// update HEAD
|
||||
const updateHeadResp = await repo.updateHead(
|
||||
"heads/master",
|
||||
'heads/master',
|
||||
commit.sha,
|
||||
false
|
||||
);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL } from "../config";
|
||||
import { objToQuery } from "../utils/url";
|
||||
import { GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL } from '../config';
|
||||
import { objToQuery } from '../utils/url';
|
||||
|
||||
export function authorizeUrl(route) {
|
||||
const params = {
|
||||
client_id: GITHUB_CLIENT_ID,
|
||||
redirect_uri: GITHUB_REDIRECT_URL,
|
||||
scope: "user:email public_repo",
|
||||
scope: 'user:email public_repo',
|
||||
state: JSON.stringify({ route })
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DBC from "../models/can/dbc";
|
||||
import DBC from '../models/can/dbc';
|
||||
|
||||
export function fetchPersistedDbc(routeName) {
|
||||
const maybeDbc = window.localStorage.getItem(routeName);
|
||||
|
@ -7,7 +7,8 @@ export function fetchPersistedDbc(routeName) {
|
|||
const dbc = new DBC(dbcText);
|
||||
|
||||
return { dbc, dbcText, dbcFilename };
|
||||
} else return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function persistDbc(routeName, { dbcFilename, dbc }) {
|
||||
|
@ -18,7 +19,7 @@ export function persistDbc(routeName, { dbcFilename, dbc }) {
|
|||
window.localStorage.setItem(routeName, dbcJson);
|
||||
}
|
||||
|
||||
const GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = "gh_auth_token";
|
||||
const GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = 'gh_auth_token';
|
||||
export function fetchPersistedGithubAuthToken() {
|
||||
return window.localStorage.getItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { raw as RawDataApi, request as Request } from "@commaai/comma-api";
|
||||
import CommaAuth from "@commaai/my-comma-auth";
|
||||
import request from "simple-get";
|
||||
import { raw as RawDataApi, request as Request } from '@commaai/comma-api';
|
||||
import CommaAuth from '@commaai/my-comma-auth';
|
||||
import request from 'simple-get';
|
||||
|
||||
const urlStore = {};
|
||||
|
||||
var initPromise;
|
||||
let initPromise;
|
||||
function ensureInit() {
|
||||
if (!initPromise) {
|
||||
initPromise = CommaAuth.init().then(function(token) {
|
||||
initPromise = CommaAuth.init().then((token) => {
|
||||
Request.configure(token);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
@ -16,8 +16,8 @@ function ensureInit() {
|
|||
}
|
||||
|
||||
export async function getLogPart(logUrl) {
|
||||
return new Promise(async function(resolve, reject) {
|
||||
request(logUrl, function(err, res) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
request(logUrl, (err, res) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import SocketIO from "socket.io-client";
|
||||
import { UNLOGGER_HOST } from "../config";
|
||||
import SocketIO from 'socket.io-client';
|
||||
import { UNLOGGER_HOST } from '../config';
|
||||
|
||||
export default class UnloggerClient {
|
||||
constructor() {
|
||||
|
@ -7,6 +7,6 @@ export default class UnloggerClient {
|
|||
}
|
||||
|
||||
seek(dongleId, baseTime, seekSeconds) {
|
||||
this.socket.emit("seek", dongleId, baseTime, seekSeconds);
|
||||
this.socket.emit('seek', dongleId, baseTime, seekSeconds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DBC from "./models/can/dbc";
|
||||
import DBC from './models/can/dbc';
|
||||
|
||||
const CivicDbc = new DBC(`
|
||||
VERSION ""
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { StyleSheet } from "aphrodite/no-important";
|
||||
import css from "../utils/css";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet } from 'aphrodite/no-important';
|
||||
import css from '../utils/css';
|
||||
|
||||
import SignalLegend from "./SignalLegend";
|
||||
import Signal from "../models/can/signal";
|
||||
import { shade } from "../utils/color";
|
||||
import DbcUtils from "../utils/dbc";
|
||||
import SignalLegend from './SignalLegend';
|
||||
import Signal from '../models/can/signal';
|
||||
import { shade } from '../utils/color';
|
||||
import DbcUtils from '../utils/dbc';
|
||||
|
||||
/*
|
||||
AddSignals component draws an 8x8 matrix
|
||||
|
@ -20,25 +20,25 @@ const Styles = StyleSheet.create({
|
|||
bit: {
|
||||
margin: 0,
|
||||
padding: 12,
|
||||
userSelect: "none",
|
||||
cursor: "pointer",
|
||||
textAlign: "center",
|
||||
position: "relative"
|
||||
userSelect: 'none',
|
||||
cursor: 'pointer',
|
||||
textAlign: 'center',
|
||||
position: 'relative'
|
||||
},
|
||||
bitSelectedStyle: {
|
||||
backgroundColor: "rgba(0,119,158,0.5)"
|
||||
backgroundColor: 'rgba(0,119,158,0.5)'
|
||||
},
|
||||
bitSignificance: {
|
||||
fontSize: 12,
|
||||
display: "block",
|
||||
position: "absolute",
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
margin: "0 auto"
|
||||
margin: '0 auto'
|
||||
},
|
||||
highlightedSignalTitle: {
|
||||
backgroundColor: "rgba(0,0,0,0.2)"
|
||||
backgroundColor: 'rgba(0,0,0,0.2)'
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -61,7 +61,7 @@ export default class AddSignals extends Component {
|
|||
|
||||
this.state = {
|
||||
bits: [],
|
||||
signals: signals,
|
||||
signals,
|
||||
signalStyles: this.calcSignalStyles(signals),
|
||||
highlightedSignal: null,
|
||||
dragStartBit: null,
|
||||
|
@ -82,28 +82,29 @@ export default class AddSignals extends Component {
|
|||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
nextProps.message.hexData !== this.props.message.hexData ||
|
||||
nextProps.messageIndex !== this.props.messageIndex ||
|
||||
JSON.stringify(nextProps.plottedSignalUids) !==
|
||||
JSON.stringify(this.props.plottedSignalUids) ||
|
||||
JSON.stringify(this.state) !== JSON.stringify(nextState)
|
||||
nextProps.message.hexData !== this.props.message.hexData
|
||||
|| nextProps.messageIndex !== this.props.messageIndex
|
||||
|| JSON.stringify(nextProps.plottedSignalUids)
|
||||
!== JSON.stringify(this.props.plottedSignalUids)
|
||||
|| JSON.stringify(this.state) !== JSON.stringify(nextState)
|
||||
);
|
||||
}
|
||||
|
||||
signalColorStyle(signal) {
|
||||
const { colors } = signal;
|
||||
|
||||
let colorRgbStr, backgroundColor;
|
||||
let colorRgbStr;
|
||||
let backgroundColor;
|
||||
if (this.state && this.state.highlightedSignal === signal.name) {
|
||||
// when signal highlighted,
|
||||
// darkened background and lightened text.
|
||||
|
||||
const darkenedColors = shade(colors, -0.5);
|
||||
const lightenedColors = shade(colors, 0.9);
|
||||
colorRgbStr = `rgb(${lightenedColors.join(",")})`;
|
||||
backgroundColor = `rgba(${darkenedColors.join(",")},0.5)`;
|
||||
colorRgbStr = `rgb(${lightenedColors.join(',')})`;
|
||||
backgroundColor = `rgba(${darkenedColors.join(',')},0.5)`;
|
||||
} else {
|
||||
const colorsCommaSep = colors.join(",");
|
||||
const colorsCommaSep = colors.join(',');
|
||||
colorRgbStr = `rgb(${colorsCommaSep})`;
|
||||
backgroundColor = `rgba(${colorsCommaSep},0.2)`;
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ export default class AddSignals extends Component {
|
|||
|
||||
calcSignalStyles(signals) {
|
||||
const signalStyles = {};
|
||||
Object.values(signals).forEach(signal => {
|
||||
Object.values(signals).forEach((signal) => {
|
||||
signalStyles[signal.name] = this.signalColorStyle(signal);
|
||||
});
|
||||
|
||||
|
@ -145,12 +146,12 @@ export default class AddSignals extends Component {
|
|||
// bitIdx in [0,64)
|
||||
// returns instance of Signal
|
||||
|
||||
return Object.values(this.state.signals).filter(signal => {
|
||||
return signal.bitDescription(bitIdx) !== null;
|
||||
})[0];
|
||||
return Object.values(this.state.signals).filter(
|
||||
(signal) => signal.bitDescription(bitIdx) !== null
|
||||
)[0];
|
||||
}
|
||||
|
||||
onSignalHover = signal => {
|
||||
onSignalHover = (signal) => {
|
||||
if (!signal) return;
|
||||
|
||||
this.setState({ highlightedSignal: signal.name }, this.updateSignalStyles);
|
||||
|
@ -214,22 +215,20 @@ export default class AddSignals extends Component {
|
|||
dragSignal.size = bitIdx - dragStartBit + 1;
|
||||
dragStartBit = bitIdx;
|
||||
}
|
||||
} else if (dragSignal.isLittleEndian) {
|
||||
dragSignal.startBit = bitIdx;
|
||||
dragSignal.size = dragStartBit - bitIdx + 1;
|
||||
dragStartBit = bitIdx;
|
||||
} else {
|
||||
if (dragSignal.isLittleEndian) {
|
||||
dragSignal.startBit = bitIdx;
|
||||
dragSignal.size = dragStartBit - bitIdx + 1;
|
||||
dragStartBit = bitIdx;
|
||||
} else {
|
||||
dragSignal.size = dragStartBit - bitIdx + 1;
|
||||
dragStartBit = bitIdx;
|
||||
}
|
||||
dragSignal.size = dragStartBit - bitIdx + 1;
|
||||
dragStartBit = bitIdx;
|
||||
}
|
||||
}
|
||||
|
||||
signals[dragSignal.name] = dragSignal;
|
||||
} else if (
|
||||
dragSignal.isLittleEndian &&
|
||||
dragStartBit === dragSignal.msbBitIndex()
|
||||
dragSignal.isLittleEndian
|
||||
&& dragStartBit === dragSignal.msbBitIndex()
|
||||
) {
|
||||
if (bitIdx < dragSignal.startBit) {
|
||||
// should not be able to drag the MSB past the LSB
|
||||
|
@ -244,8 +243,8 @@ export default class AddSignals extends Component {
|
|||
signals[dragSignal.name] = dragSignal;
|
||||
dragStartBit = dragSignal.msbBitIndex();
|
||||
} else if (
|
||||
!dragSignal.isLittleEndian &&
|
||||
dragStartBit === dragSignal.lsbBitIndex()
|
||||
!dragSignal.isLittleEndian
|
||||
&& dragStartBit === dragSignal.lsbBitIndex()
|
||||
) {
|
||||
const diff = bitIdx - dragStartBit;
|
||||
if (dragSignal.bitDescription(bitIdx) === null) {
|
||||
|
@ -271,7 +270,7 @@ export default class AddSignals extends Component {
|
|||
}
|
||||
};
|
||||
|
||||
onSignalHoverEnd = signal => {
|
||||
onSignalHoverEnd = (signal) => {
|
||||
if (!signal) return;
|
||||
|
||||
this.setState({ highlightedSignal: null }, this.updateSignalStyles);
|
||||
|
@ -279,10 +278,10 @@ export default class AddSignals extends Component {
|
|||
|
||||
nextNewSignalName() {
|
||||
const existingNames = Object.keys(this.state.signals);
|
||||
let signalNum = 1,
|
||||
signalName;
|
||||
let signalNum = 1;
|
||||
let signalName;
|
||||
do {
|
||||
signalName = "NEW_SIGNAL_" + signalNum;
|
||||
signalName = `NEW_SIGNAL_${signalNum}`;
|
||||
signalNum++;
|
||||
} while (existingNames.indexOf(signalName) !== -1);
|
||||
|
||||
|
@ -300,7 +299,7 @@ export default class AddSignals extends Component {
|
|||
const signal = new Signal({
|
||||
name: this.nextNewSignalName(),
|
||||
startBit,
|
||||
size: size,
|
||||
size,
|
||||
isLittleEndian
|
||||
});
|
||||
let { signals } = this.state;
|
||||
|
@ -319,10 +318,8 @@ export default class AddSignals extends Component {
|
|||
return;
|
||||
}
|
||||
}
|
||||
const isDragAcrossSingleByte =
|
||||
Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8);
|
||||
const isDragDirectionUp =
|
||||
!isDragAcrossSingleByte && dragEndBit < dragStartBit;
|
||||
const isDragAcrossSingleByte = Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8);
|
||||
const isDragDirectionUp = !isDragAcrossSingleByte && dragEndBit < dragStartBit;
|
||||
|
||||
let isLittleEndian;
|
||||
if (isDragAcrossSingleByte || !isDragDirectionUp) {
|
||||
|
@ -330,30 +327,27 @@ export default class AddSignals extends Component {
|
|||
} else {
|
||||
isLittleEndian = dragStartBit % 8 >= 4;
|
||||
}
|
||||
let size,
|
||||
startBit = dragStartBit;
|
||||
let size;
|
||||
let startBit = dragStartBit;
|
||||
|
||||
if (isDragAcrossSingleByte) {
|
||||
size = Math.abs(dragEndBit - dragStartBit) + 1;
|
||||
} else {
|
||||
if (isLittleEndian) {
|
||||
if (dragEndBit > dragStartBit) {
|
||||
startBit = dragStartBit;
|
||||
size = dragEndBit - dragStartBit + 1;
|
||||
} else {
|
||||
startBit = dragEndBit;
|
||||
size = dragStartBit - dragEndBit + 1;
|
||||
}
|
||||
} else if (isLittleEndian) {
|
||||
if (dragEndBit > dragStartBit) {
|
||||
startBit = dragStartBit;
|
||||
size = dragEndBit - dragStartBit + 1;
|
||||
} else {
|
||||
if (dragEndBit < dragStartBit) {
|
||||
startBit = dragEndBit;
|
||||
}
|
||||
size =
|
||||
Math.abs(
|
||||
DbcUtils.bigEndianBitIndex(dragEndBit) -
|
||||
DbcUtils.bigEndianBitIndex(dragStartBit)
|
||||
) + 1;
|
||||
startBit = dragEndBit;
|
||||
size = dragStartBit - dragEndBit + 1;
|
||||
}
|
||||
} else {
|
||||
if (dragEndBit < dragStartBit) {
|
||||
startBit = dragEndBit;
|
||||
}
|
||||
size = Math.abs(
|
||||
DbcUtils.bigEndianBitIndex(dragEndBit)
|
||||
- DbcUtils.bigEndianBitIndex(dragStartBit)
|
||||
) + 1;
|
||||
}
|
||||
|
||||
this.createSignal({ startBit, size, isLittleEndian });
|
||||
|
@ -362,7 +356,7 @@ export default class AddSignals extends Component {
|
|||
|
||||
onBitMouseUp(dragEndBit, signal) {
|
||||
if (this.state.dragStartBit !== null) {
|
||||
let { dragStartBit } = this.state;
|
||||
const { dragStartBit } = this.state;
|
||||
|
||||
if (dragEndBit !== dragStartBit) {
|
||||
// one-bit signal requires double click
|
||||
|
@ -380,24 +374,22 @@ export default class AddSignals extends Component {
|
|||
const entry = entries[this.props.messageIndex];
|
||||
|
||||
return entry.hexData.substr(byteIdx * 2, 2);
|
||||
} else {
|
||||
return "--";
|
||||
}
|
||||
return '--';
|
||||
}
|
||||
|
||||
bitValue(byteIdx, byteBitIdx) {
|
||||
const { entries } = this.props.message;
|
||||
if (this.props.messageIndex < entries.length) {
|
||||
const entry = entries[this.props.messageIndex];
|
||||
const data = Buffer.from(entry.hexData, "hex");
|
||||
const data = Buffer.from(entry.hexData, 'hex');
|
||||
if (byteIdx >= data.length) {
|
||||
return "-";
|
||||
return '-';
|
||||
}
|
||||
const byte = data.readInt8(byteIdx);
|
||||
return (byte >> byteBitIdx) & 1;
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
|
||||
bitIsContainedInSelection(bitIdx, isLittleEndian = false) {
|
||||
|
@ -405,22 +397,21 @@ export default class AddSignals extends Component {
|
|||
|
||||
if (isLittleEndian || dragStartBit % 8 < 4) {
|
||||
return (
|
||||
dragStartBit !== null &&
|
||||
dragCurrentBit !== null &&
|
||||
bitIdx >= dragStartBit &&
|
||||
bitIdx <= dragCurrentBit
|
||||
);
|
||||
} else {
|
||||
const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit);
|
||||
const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit);
|
||||
const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx);
|
||||
return (
|
||||
dragStartBit !== null &&
|
||||
dragCurrentBit !== null &&
|
||||
bigEndianBitIdx >= bigEndianStartBit &&
|
||||
bigEndianBitIdx <= bigEndianCurrentBit
|
||||
dragStartBit !== null
|
||||
&& dragCurrentBit !== null
|
||||
&& bitIdx >= dragStartBit
|
||||
&& bitIdx <= dragCurrentBit
|
||||
);
|
||||
}
|
||||
const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit);
|
||||
const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit);
|
||||
const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx);
|
||||
return (
|
||||
dragStartBit !== null
|
||||
&& dragCurrentBit !== null
|
||||
&& bigEndianBitIdx >= bigEndianStartBit
|
||||
&& bigEndianBitIdx <= bigEndianCurrentBit
|
||||
);
|
||||
}
|
||||
|
||||
onBitDoubleClick(startBit, signal) {
|
||||
|
@ -434,26 +425,26 @@ export default class AddSignals extends Component {
|
|||
const rows = [];
|
||||
let rowCount;
|
||||
if (message.frame && message.frame.size) {
|
||||
rowCount = Math.floor(message.frame.size * 8 / 8);
|
||||
rowCount = Math.floor((message.frame.size * 8) / 8);
|
||||
} else {
|
||||
rowCount = 8;
|
||||
}
|
||||
|
||||
for (var i = 0; i < rowCount; i++) {
|
||||
for (let i = 0; i < rowCount; i++) {
|
||||
const rowBits = [];
|
||||
for (var j = 7; j >= 0; j--) {
|
||||
for (let j = 7; j >= 0; j--) {
|
||||
const bitIdx = i * 8 + j;
|
||||
const signal = this.signalForBit(bitIdx);
|
||||
let bitStyle = null,
|
||||
bitSignificance = "";
|
||||
let bitStyle = null;
|
||||
let bitSignificance = '';
|
||||
if (signal) {
|
||||
bitStyle = this.state.signalStyles[signal.name] || null;
|
||||
const bitDesc = signal.bitDescription(bitIdx);
|
||||
bitSignificance = bitDesc.isMsb ? "msb" : bitDesc.isLsb ? "lsb" : "";
|
||||
bitSignificance = bitDesc.isMsb ? 'msb' : bitDesc.isLsb ? 'lsb' : '';
|
||||
} else if (this.bitIsContainedInSelection(bitIdx)) {
|
||||
bitStyle = Styles.bitSelectedStyle;
|
||||
}
|
||||
const className = css("bit", Styles.bit, bitStyle);
|
||||
const className = css('bit', Styles.bit, bitStyle);
|
||||
const bitValue = this.bitValue(i, j);
|
||||
|
||||
rowBits.push(
|
||||
|
@ -474,7 +465,7 @@ export default class AddSignals extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
rowBits.push(<td key={"hex-repr"}>{this.byteValueHex(i)}</td>);
|
||||
rowBits.push(<td key="hex-repr">{this.byteValueHex(i)}</td>);
|
||||
rows.push(<tr key={i.toString()}>{rowBits}</tr>);
|
||||
}
|
||||
|
||||
|
@ -495,7 +486,7 @@ export default class AddSignals extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
onTentativeSignalChange = signal => {
|
||||
onTentativeSignalChange = (signal) => {
|
||||
// Tentative signal changes are not propagated up
|
||||
// but their effects are displayed in the bitmatrix
|
||||
const { signals } = this.state;
|
||||
|
@ -506,7 +497,7 @@ export default class AddSignals extends Component {
|
|||
onSignalChange = (signal, oldSignal) => {
|
||||
const { signals } = this.state;
|
||||
|
||||
for (let signalName in signals) {
|
||||
for (const signalName in signals) {
|
||||
if (signals[signalName].uid === signal.uid) {
|
||||
delete signals[signalName];
|
||||
}
|
||||
|
@ -516,7 +507,7 @@ export default class AddSignals extends Component {
|
|||
this.setState({ signals }, this.propagateUpSignalChange);
|
||||
};
|
||||
|
||||
onSignalRemove = signal => {
|
||||
onSignalRemove = (signal) => {
|
||||
const { signals } = this.state;
|
||||
delete signals[signal.name];
|
||||
this.setState({ signals }, this.propagateUpSignalChange);
|
||||
|
@ -546,7 +537,8 @@ export default class AddSignals extends Component {
|
|||
{this.props.message.entries[this.props.messageIndex] ? (
|
||||
<div className="cabana-explorer-signals-time">
|
||||
<p>
|
||||
time:{" "}
|
||||
time:
|
||||
{' '}
|
||||
{this.props.message.entries[
|
||||
this.props.messageIndex
|
||||
].relTime.toFixed(3)}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React, { Component } from "react";
|
||||
import Measure from "react-measure";
|
||||
import PropTypes from "prop-types";
|
||||
import cx from "classnames";
|
||||
import { Vega } from "react-vega";
|
||||
import React, { Component } from 'react';
|
||||
import Measure from 'react-measure';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import { Vega } from 'react-vega';
|
||||
|
||||
import Signal from "../models/can/signal";
|
||||
import GraphData from "../models/graph-data";
|
||||
import CanPlotSpec from "../vega/CanPlot";
|
||||
import debounce from "../utils/debounce";
|
||||
import Signal from '../models/can/signal';
|
||||
import GraphData from '../models/graph-data';
|
||||
import CanPlotSpec from '../vega/CanPlot';
|
||||
import debounce from '../utils/debounce';
|
||||
|
||||
const DefaultPlotInnerStyle = {
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0
|
||||
};
|
||||
|
@ -63,10 +63,10 @@ export default class CanGraph extends Component {
|
|||
getGraphData(props) {
|
||||
let firstRelTime = -1;
|
||||
let lastRelTime = -1;
|
||||
let series = props.plottedSignals
|
||||
.map(signals => {
|
||||
const series = props.plottedSignals
|
||||
.map((signals) => {
|
||||
const { messageId, signalUid } = signals;
|
||||
let entries = props.messages[messageId].entries;
|
||||
const { entries } = props.messages[messageId];
|
||||
if (entries.length) {
|
||||
let messageRelTime = entries[0].relTime;
|
||||
if (firstRelTime === -1) {
|
||||
|
@ -109,15 +109,15 @@ export default class CanGraph extends Component {
|
|||
|
||||
segmentIsNew(newSegment) {
|
||||
return (
|
||||
newSegment.length !== this.props.segment.length ||
|
||||
!newSegment.every((val, idx) => this.props.segment[idx] === val)
|
||||
newSegment.length !== this.props.segment.length
|
||||
|| !newSegment.every((val, idx) => this.props.segment[idx] === val)
|
||||
);
|
||||
}
|
||||
|
||||
visualChanged(prevProps, nextProps) {
|
||||
return (
|
||||
prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop ||
|
||||
JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos)
|
||||
prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop
|
||||
|| JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -138,46 +138,46 @@ export default class CanGraph extends Component {
|
|||
}
|
||||
|
||||
updateBounds = debounce(() => {
|
||||
this.view.signal("width", this.state.bounds.width - 70);
|
||||
this.view.signal("height", 0.4 * (this.state.bounds.width - 70)); // 5:2 aspect ratio
|
||||
this.view.signal('width', this.state.bounds.width - 70);
|
||||
this.view.signal('height', 0.4 * (this.state.bounds.width - 70)); // 5:2 aspect ratio
|
||||
this.view.run();
|
||||
}, 100);
|
||||
|
||||
insertData = debounce(() => {
|
||||
if (!this.view) {
|
||||
console.log("Cannot insertData");
|
||||
console.log('Cannot insertData');
|
||||
return;
|
||||
}
|
||||
|
||||
// adding plot points by diff isn't faster since it basically has to be n^2
|
||||
// out-of-order events make it so that you can't just check the bounds
|
||||
let { series } = this.state.data;
|
||||
let changeset = this.view
|
||||
const { series } = this.state.data;
|
||||
const changeset = this.view
|
||||
.changeset()
|
||||
.remove(v => true)
|
||||
.remove((v) => true)
|
||||
.insert(series);
|
||||
this.view.change("table", changeset);
|
||||
this.view.change('table', changeset);
|
||||
this.view.run();
|
||||
}, 250);
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.dragPos &&
|
||||
JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos)
|
||||
nextProps.dragPos
|
||||
&& JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos)
|
||||
) {
|
||||
this.updateStyleFromDragPos(nextProps.dragPos);
|
||||
} else if (!nextProps.dragPos && this.state.plotInnerStyle !== null) {
|
||||
this.setState({ plotInnerStyle: null });
|
||||
}
|
||||
if (
|
||||
this.props.messages !== nextProps.messages ||
|
||||
this.props.plottedSignal !== nextProps.plottedSignal
|
||||
this.props.messages !== nextProps.messages
|
||||
|| this.props.plottedSignal !== nextProps.plottedSignal
|
||||
) {
|
||||
let data = this.getGraphData(nextProps);
|
||||
const data = this.getGraphData(nextProps);
|
||||
if (
|
||||
data.series.length === this.state.data.series.length &&
|
||||
data.firstRelTime === this.state.data.firstRelTime &&
|
||||
data.lastRelTime === this.state.data.lastRelTime
|
||||
data.series.length === this.state.data.series.length
|
||||
&& data.firstRelTime === this.state.data.firstRelTime
|
||||
&& data.lastRelTime === this.state.data.lastRelTime
|
||||
) {
|
||||
// do nothing, the data didn't *actually* change
|
||||
} else {
|
||||
|
@ -188,6 +188,7 @@ export default class CanGraph extends Component {
|
|||
this.setState({ spec: this.getGraphSpec(nextProps) });
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
if (!this.view) {
|
||||
return true;
|
||||
|
@ -199,30 +200,31 @@ export default class CanGraph extends Component {
|
|||
this.insertData();
|
||||
}
|
||||
if (this.props.currentTime !== nextProps.currentTime) {
|
||||
this.view.signal("videoTime", nextProps.currentTime);
|
||||
this.view.signal('videoTime', nextProps.currentTime);
|
||||
}
|
||||
if (this.segmentIsNew(nextProps.segment)) {
|
||||
if (nextProps.segment.length > 0) {
|
||||
// Set segmented domain
|
||||
this.view.signal("segment", nextProps.segment);
|
||||
this.view.signal('segment', nextProps.segment);
|
||||
} else {
|
||||
// Reset segment to full domain
|
||||
this.view.signal("segment", 0);
|
||||
this.view.signal('segment', 0);
|
||||
}
|
||||
}
|
||||
this.view.runAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
componentDidUpdate(oldProps, oldState) {
|
||||
if (this.view) {
|
||||
if (this.props.segment.length > 0) {
|
||||
// Set segmented domain
|
||||
this.view.signal("segment", this.props.segment);
|
||||
this.view.signal('segment', this.props.segment);
|
||||
} else {
|
||||
// Reset segment to full domain
|
||||
this.view.signal("segment", 0);
|
||||
this.view.signal('segment', 0);
|
||||
}
|
||||
this.view.signal("videoTime", this.props.currentTime);
|
||||
this.view.signal('videoTime', this.props.currentTime);
|
||||
this.view.runAsync();
|
||||
}
|
||||
}
|
||||
|
@ -241,9 +243,9 @@ export default class CanGraph extends Component {
|
|||
this.onPlotResize();
|
||||
}
|
||||
if (this.props.segment.length > 0) {
|
||||
view.signal("segment", this.props.segment);
|
||||
view.signal('segment', this.props.segment);
|
||||
}
|
||||
view.signal("videoTime", this.props.currentTime);
|
||||
view.signal('videoTime', this.props.currentTime);
|
||||
|
||||
this.insertData();
|
||||
}
|
||||
|
@ -319,7 +321,7 @@ export default class CanGraph extends Component {
|
|||
render() {
|
||||
const { plotInnerStyle } = this.state;
|
||||
const canReceiveDropClass = this.props.canReceiveGraphDrop
|
||||
? "is-droppable"
|
||||
? 'is-droppable'
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -329,7 +331,7 @@ export default class CanGraph extends Component {
|
|||
>
|
||||
<div
|
||||
className={cx(
|
||||
"cabana-explorer-visuals-plot-inner",
|
||||
'cabana-explorer-visuals-plot-inner',
|
||||
canReceiveDropClass
|
||||
)}
|
||||
style={plotInnerStyle || null}
|
||||
|
@ -344,13 +346,13 @@ export default class CanGraph extends Component {
|
|||
({ messageId, signalUid, messageName }) => {
|
||||
const signal = Object.values(
|
||||
this.props.messages[messageId].frame.signals
|
||||
).find(s => s.uid === signalUid);
|
||||
).find((s) => s.uid === signalUid);
|
||||
const { colors } = signal;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="cabana-explorer-visuals-plot-header"
|
||||
key={messageId + "_" + signal.uid}
|
||||
key={`${messageId}_${signal.uid}`}
|
||||
>
|
||||
<div className="cabana-explorer-visuals-plot-header-toggle">
|
||||
<button
|
||||
|
@ -377,29 +379,27 @@ export default class CanGraph extends Component {
|
|||
}
|
||||
)}
|
||||
<Measure bounds onResize={this.onPlotResize}>
|
||||
{({ measureRef }) => {
|
||||
return (
|
||||
<div
|
||||
ref={measureRef}
|
||||
className="cabana-explorer-visuals-plot-container"
|
||||
>
|
||||
<Vega
|
||||
onNewView={this.onNewView}
|
||||
logLevel={1}
|
||||
signalListeners={{
|
||||
clickTime: this.onSignalClickTime,
|
||||
segment: this.onSignalSegment
|
||||
}}
|
||||
renderer={"canvas"}
|
||||
spec={this.state.spec}
|
||||
actions={false}
|
||||
data={{
|
||||
table: this.state.data.series
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
{({ measureRef }) => (
|
||||
<div
|
||||
ref={measureRef}
|
||||
className="cabana-explorer-visuals-plot-container"
|
||||
>
|
||||
<Vega
|
||||
onNewView={this.onNewView}
|
||||
logLevel={1}
|
||||
signalListeners={{
|
||||
clickTime: this.onSignalClickTime,
|
||||
segment: this.onSignalSegment
|
||||
}}
|
||||
renderer="canvas"
|
||||
spec={this.state.spec}
|
||||
actions={false}
|
||||
data={{
|
||||
table: this.state.data.series
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Measure>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import CanGraph from "./CanGraph";
|
||||
import CanGraph from './CanGraph';
|
||||
|
||||
require("element-closest");
|
||||
require('element-closest');
|
||||
|
||||
export default class CanGraphList extends Component {
|
||||
static propTypes = {
|
||||
|
@ -46,9 +46,8 @@ export default class CanGraphList extends Component {
|
|||
determineDraggingGraph() {
|
||||
const { draggingSignal } = this.state;
|
||||
return this.plotRefs.find(
|
||||
({ messageId, signalUid }) =>
|
||||
draggingSignal.messageId === messageId &&
|
||||
draggingSignal.signalUid === signalUid
|
||||
({ messageId, signalUid }) => draggingSignal.messageId === messageId
|
||||
&& draggingSignal.signalUid === signalUid
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -66,13 +65,12 @@ export default class CanGraphList extends Component {
|
|||
draggingGraph.ref.hidden = true;
|
||||
const ele = document.elementFromPoint(e.clientX, e.clientY);
|
||||
draggingGraph.ref.hidden = false;
|
||||
const closestPlot = ele.closest(".cabana-explorer-visuals-plot");
|
||||
const closestPlot = ele.closest('.cabana-explorer-visuals-plot');
|
||||
const closestPlotRef = this.plotRefs.find(
|
||||
({ ref, messageId, signalUid }) =>
|
||||
!(
|
||||
messageId === draggingGraph.messageId &&
|
||||
signalUid === draggingGraph.signalUid
|
||||
) && ref.isEqualNode(closestPlot)
|
||||
({ ref, messageId, signalUid }) => !(
|
||||
messageId === draggingGraph.messageId
|
||||
&& signalUid === draggingGraph.signalUid
|
||||
) && ref.isEqualNode(closestPlot)
|
||||
);
|
||||
if (closestPlotRef) {
|
||||
this.setState({ graphToReceiveDrop: closestPlotRef });
|
||||
|
@ -107,7 +105,7 @@ export default class CanGraphList extends Component {
|
|||
let { plotRefs } = this;
|
||||
plotRefs = plotRefs
|
||||
.filter(
|
||||
ref => !(ref.messageId === messageId && ref.signalUid === signalUid)
|
||||
(ref) => !(ref.messageId === messageId && ref.signalUid === signalUid)
|
||||
)
|
||||
.concat([{ messageId, signalUid, ref }]);
|
||||
this.plotRefs = plotRefs;
|
||||
|
@ -119,33 +117,29 @@ export default class CanGraphList extends Component {
|
|||
const { messageId, signalUid } = plottedSignals[0];
|
||||
const msg = this.props.messages[messageId];
|
||||
const signal = Object.values(msg.frame.signals).find(
|
||||
s => s.uid === signalUid
|
||||
(s) => s.uid === signalUid
|
||||
);
|
||||
|
||||
if (!this.plotListRef) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const isDragging =
|
||||
draggingSignal.signalUid === signalUid &&
|
||||
draggingSignal.messageId === messageId;
|
||||
const canReceiveGraphDrop =
|
||||
graphToReceiveDrop &&
|
||||
graphToReceiveDrop.signalUid === signalUid &&
|
||||
graphToReceiveDrop.messageId === messageId;
|
||||
plottedSignals = plottedSignals.map(plottedSignal => {
|
||||
return {
|
||||
messageName: this.props.messages[plottedSignal.messageId].frame.name,
|
||||
...plottedSignal
|
||||
};
|
||||
});
|
||||
const isDragging = draggingSignal.signalUid === signalUid
|
||||
&& draggingSignal.messageId === messageId;
|
||||
const canReceiveGraphDrop = graphToReceiveDrop
|
||||
&& graphToReceiveDrop.signalUid === signalUid
|
||||
&& graphToReceiveDrop.messageId === messageId;
|
||||
plottedSignals = plottedSignals.map((plottedSignal) => ({
|
||||
messageName: this.props.messages[plottedSignal.messageId].frame.name,
|
||||
...plottedSignal
|
||||
}));
|
||||
const key = plottedSignals.reduce(
|
||||
(key, { messageId, signalUid }) => key + messageId + "_" + signalUid,
|
||||
""
|
||||
(key, { messageId, signalUid }) => `${key + messageId}_${signalUid}`,
|
||||
''
|
||||
);
|
||||
return (
|
||||
<CanGraph
|
||||
onGraphRefAvailable={ref => {
|
||||
onGraphRefAvailable={(ref) => {
|
||||
this.addCanGraphRef(ref, messageId, signalUid);
|
||||
}}
|
||||
key={key}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ReactList from "react-list";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactList from 'react-list';
|
||||
|
||||
import cx from "classnames";
|
||||
import cx from 'classnames';
|
||||
|
||||
export default class CanLog extends Component {
|
||||
static ITEMS_PER_PAGE = 50;
|
||||
|
@ -52,21 +52,20 @@ export default class CanLog extends Component {
|
|||
? nextProps.message.entries.length
|
||||
: 0;
|
||||
|
||||
const shouldUpdate =
|
||||
this.props.message !== nextProps.message ||
|
||||
nextMessageLength !== curMessageLength ||
|
||||
nextProps.messageIndex !== this.props.messageIndex ||
|
||||
nextProps.plottedSignals.length !== this.props.plottedSignals.length ||
|
||||
JSON.stringify(nextProps.segmentIndices) !==
|
||||
JSON.stringify(this.props.segmentIndices) ||
|
||||
JSON.stringify(nextState) !== JSON.stringify(this.state) ||
|
||||
this.props.message !== nextProps.message ||
|
||||
(this.props.message !== undefined &&
|
||||
nextProps.message !== undefined &&
|
||||
this.props.message.frame !== undefined &&
|
||||
nextProps.message.frame !== undefined &&
|
||||
JSON.stringify(this.props.message.frame) !==
|
||||
JSON.stringify(nextProps.message.frame));
|
||||
const shouldUpdate = this.props.message !== nextProps.message
|
||||
|| nextMessageLength !== curMessageLength
|
||||
|| nextProps.messageIndex !== this.props.messageIndex
|
||||
|| nextProps.plottedSignals.length !== this.props.plottedSignals.length
|
||||
|| JSON.stringify(nextProps.segmentIndices)
|
||||
!== JSON.stringify(this.props.segmentIndices)
|
||||
|| JSON.stringify(nextState) !== JSON.stringify(this.state)
|
||||
|| this.props.message !== nextProps.message
|
||||
|| (this.props.message !== undefined
|
||||
&& nextProps.message !== undefined
|
||||
&& this.props.message.frame !== undefined
|
||||
&& nextProps.message.frame !== undefined
|
||||
&& JSON.stringify(this.props.message.frame)
|
||||
!== JSON.stringify(nextProps.message.frame));
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
@ -88,24 +87,23 @@ export default class CanLog extends Component {
|
|||
collapseMessage(msg, msgIdx) {
|
||||
this.setState({
|
||||
expandedMessages: this.state.expandedMessages.filter(
|
||||
expMsgTime => expMsgTime !== msg.time
|
||||
(expMsgTime) => expMsgTime !== msg.time
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
isSignalPlotted(msgId, signalUid) {
|
||||
const plottedSignal = this.props.plottedSignals.find(plot =>
|
||||
plot.some(
|
||||
signal => signal.messageId === msgId && signal.signalUid === signalUid
|
||||
)
|
||||
);
|
||||
const plottedSignal = this.props.plottedSignals.find((plot) => plot.some(
|
||||
(signal) => signal.messageId === msgId && signal.signalUid === signalUid
|
||||
));
|
||||
return plottedSignal !== undefined;
|
||||
}
|
||||
|
||||
signalValuePretty(signal, value) {
|
||||
if (signal.isFloat) {
|
||||
return value.toFixed(3);
|
||||
} else return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
isMessageExpanded(msg) {
|
||||
|
@ -124,15 +122,13 @@ export default class CanLog extends Component {
|
|||
if (!this.props.message.frame) {
|
||||
return;
|
||||
}
|
||||
const msgIsExpanded =
|
||||
this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
|
||||
const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
|
||||
|
||||
const msgHasSignals =
|
||||
Object.keys(this.props.message.frame.signals).length > 0;
|
||||
const msgHasSignals = Object.keys(this.props.message.frame.signals).length > 0;
|
||||
if (msgIsExpanded && msgHasSignals) {
|
||||
this.setState({
|
||||
expandedMessages: this.state.expandedMessages.filter(
|
||||
expMsgTime => expMsgTime !== msgEntry.time
|
||||
(expMsgTime) => expMsgTime !== msgEntry.time
|
||||
)
|
||||
});
|
||||
} else if (msgHasSignals) {
|
||||
|
@ -141,7 +137,6 @@ export default class CanLog extends Component {
|
|||
});
|
||||
this.props.onMessageExpanded();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,10 +150,10 @@ export default class CanLog extends Component {
|
|||
// Signal removed?
|
||||
return null;
|
||||
}
|
||||
const unit = signal.unit.length > 0 ? signal.unit : "units";
|
||||
const unit = signal.unit.length > 0 ? signal.unit : 'units';
|
||||
const isPlotted = this.isSignalPlotted(message.id, signal.uid);
|
||||
const plottedButtonClass = isPlotted ? null : "button--alpha";
|
||||
const plottedButtonText = isPlotted ? "Hide Plot" : "Show Plot";
|
||||
const plottedButtonClass = isPlotted ? null : 'button--alpha';
|
||||
const plottedButtonText = isPlotted ? 'Hide Plot' : 'Show Plot';
|
||||
return (
|
||||
<div key={name} className="signals-log-list-signal">
|
||||
<div className="signals-log-list-signal-message">
|
||||
|
@ -166,8 +161,11 @@ export default class CanLog extends Component {
|
|||
</div>
|
||||
<div className="signals-log-list-signal-value">
|
||||
<span>
|
||||
(<strong>{this.signalValuePretty(signal, value)}</strong>{" "}
|
||||
{unit})
|
||||
(
|
||||
<strong>{this.signalValuePretty(signal, value)}</strong>
|
||||
{' '}
|
||||
{unit}
|
||||
)
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
|
@ -176,7 +174,7 @@ export default class CanLog extends Component {
|
|||
this.toggleSignalPlot(message.id, signal.uid, isPlotted);
|
||||
}}
|
||||
>
|
||||
<button className={cx("button--tiny", plottedButtonClass)}>
|
||||
<button className={cx('button--tiny', plottedButtonClass)}>
|
||||
<span>{plottedButtonText}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -189,15 +187,14 @@ export default class CanLog extends Component {
|
|||
|
||||
renderLogListItemMessage(msgEntry, key) {
|
||||
const { message } = this.props;
|
||||
const msgIsExpanded =
|
||||
this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
|
||||
const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
|
||||
const msgHasSignals = Object.keys(msgEntry.signals).length > 0;
|
||||
const hasSignalsClass = msgHasSignals ? "has-signals" : null;
|
||||
const expandedClass = msgIsExpanded ? "is-expanded" : null;
|
||||
const hasSignalsClass = msgHasSignals ? 'has-signals' : null;
|
||||
const expandedClass = msgIsExpanded ? 'is-expanded' : null;
|
||||
const row = (
|
||||
<div
|
||||
key={key}
|
||||
className={cx("signals-log-list-item", hasSignalsClass, expandedClass)}
|
||||
className={cx('signals-log-list-item', hasSignalsClass, expandedClass)}
|
||||
>
|
||||
<div
|
||||
className="signals-log-list-item-header"
|
||||
|
@ -211,7 +208,11 @@ export default class CanLog extends Component {
|
|||
</strong>
|
||||
</div>
|
||||
<div className="signals-log-list-time">
|
||||
<span>[{msgEntry.relTime.toFixed(3)}]</span>
|
||||
<span>
|
||||
[
|
||||
{msgEntry.relTime.toFixed(3)}
|
||||
]
|
||||
</span>
|
||||
</div>
|
||||
<div className="signals-log-list-bytes">
|
||||
<span className="t-mono">{msgEntry.hexData}</span>
|
||||
|
@ -239,9 +240,8 @@ export default class CanLog extends Component {
|
|||
this.props.message.entries[offset + index],
|
||||
key
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
renderLogList(items, ref) {
|
||||
|
@ -263,14 +263,15 @@ export default class CanLog extends Component {
|
|||
const { segmentIndices, messageIndex } = this.props;
|
||||
if (messageIndex > 0) {
|
||||
return this.props.message.entries.length - messageIndex;
|
||||
} else if (segmentIndices.length === 2) {
|
||||
return segmentIndices[1] - segmentIndices[0];
|
||||
} else if (this.props.message) {
|
||||
return this.props.message.entries.length;
|
||||
} else {
|
||||
// no message yet
|
||||
return 0;
|
||||
}
|
||||
if (segmentIndices.length === 2) {
|
||||
return segmentIndices[1] - segmentIndices[0];
|
||||
}
|
||||
if (this.props.message) {
|
||||
return this.props.message.entries.length;
|
||||
}
|
||||
// no message yet
|
||||
return 0;
|
||||
}
|
||||
|
||||
onExpandAllChanged(e) {
|
||||
|
@ -282,16 +283,18 @@ export default class CanLog extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
let expandAllText = this.state.allPacketsExpanded
|
||||
? "Collapse All"
|
||||
: "Expand All";
|
||||
let expandAllClass = this.state.allPacketsExpanded ? null : "button--alpha";
|
||||
const expandAllText = this.state.allPacketsExpanded
|
||||
? 'Collapse All'
|
||||
: 'Expand All';
|
||||
const expandAllClass = this.state.allPacketsExpanded
|
||||
? null
|
||||
: 'button--alpha';
|
||||
return (
|
||||
<div className="cabana-explorer-signals-log">
|
||||
<div className="cabana-explorer-signals-log-header">
|
||||
<strong>Message Packets</strong>
|
||||
<button
|
||||
className={cx("button--tiny", expandAllClass)}
|
||||
className={cx('button--tiny', expandAllClass)}
|
||||
onClick={this.toggleExpandAllPackets}
|
||||
>
|
||||
{expandAllText}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class DbcUpload extends Component {
|
||||
static propTypes = {
|
||||
onDbcLoaded: PropTypes.func
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dbcText: ""
|
||||
dbcText: ''
|
||||
};
|
||||
|
||||
this.onTextChanged = this.onTextChanged.bind(this);
|
||||
|
@ -17,7 +18,7 @@ export default class DbcUpload extends Component {
|
|||
onTextChanged(e) {
|
||||
const dbcText = e.target.value;
|
||||
this.setState({ dbcText });
|
||||
this.props.onDbcLoaded("from paste", dbcText);
|
||||
this.props.onDbcLoaded('from paste', dbcText);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Modal from "./Modals/baseModal";
|
||||
import Modal from './Modals/baseModal';
|
||||
|
||||
export default class EditMessageModal extends Component {
|
||||
static propTypes = {
|
||||
|
@ -32,9 +32,7 @@ export default class EditMessageModal extends Component {
|
|||
this.setState({ messageFrame });
|
||||
}
|
||||
|
||||
editTransmitter(transmitter) {
|
||||
return;
|
||||
}
|
||||
editTransmitter(transmitter) {}
|
||||
|
||||
renderActions() {
|
||||
return (
|
||||
|
@ -67,7 +65,7 @@ export default class EditMessageModal extends Component {
|
|||
type="text"
|
||||
id="message_name"
|
||||
value={this.state.messageFrame.name}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
const { messageFrame } = this.state;
|
||||
messageFrame.name = e.target.value;
|
||||
this.setState({ messageFrame });
|
||||
|
@ -83,7 +81,7 @@ export default class EditMessageModal extends Component {
|
|||
type="number"
|
||||
id="message_size"
|
||||
value={this.state.messageFrame.size}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
const { messageFrame } = this.state;
|
||||
if (e.target.value > 8) {
|
||||
return;
|
||||
|
@ -102,23 +100,21 @@ export default class EditMessageModal extends Component {
|
|||
</label>
|
||||
<div className="form-field-inset">
|
||||
<ul className="form-field-inset-list">
|
||||
{this.state.messageFrame.transmitters.map(transmitter => {
|
||||
return (
|
||||
<li className="form-field-inset-list-item" key={transmitter}>
|
||||
<div className="form-field-inset-list-item-title">
|
||||
<span>{transmitter}</span>
|
||||
</div>
|
||||
<div className="form-field-inset-list-item-action">
|
||||
<button className="button--tiny button--alpha">
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
{this.state.messageFrame.transmitters.map((transmitter) => (
|
||||
<li className="form-field-inset-list-item" key={transmitter}>
|
||||
<div className="form-field-inset-list-item-title">
|
||||
<span>{transmitter}</span>
|
||||
</div>
|
||||
<div className="form-field-inset-list-item-action">
|
||||
<button className="button--tiny button--alpha">Edit</button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
<button className="button--tiny button--alpha">
|
||||
<span>
|
||||
<i className="fa fa-plus" /> Add Transmitter
|
||||
<i className="fa fa-plus" />
|
||||
{' '}
|
||||
Add Transmitter
|
||||
</span>
|
||||
</button>
|
||||
</ul>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import cx from "classnames";
|
||||
import cx from 'classnames';
|
||||
|
||||
import AddSignals from "./AddSignals";
|
||||
import CanGraphList from "./CanGraphList";
|
||||
import RouteVideoSync from "./RouteVideoSync";
|
||||
import CanLog from "./CanLog";
|
||||
import Entries from "../models/can/entries";
|
||||
import debounce from "../utils/debounce";
|
||||
import PartSelector from "./PartSelector";
|
||||
import PlaySpeedSelector from "./PlaySpeedSelector";
|
||||
import AddSignals from './AddSignals';
|
||||
import CanGraphList from './CanGraphList';
|
||||
import RouteVideoSync from './RouteVideoSync';
|
||||
import CanLog from './CanLog';
|
||||
import Entries from '../models/can/entries';
|
||||
import debounce from '../utils/debounce';
|
||||
import PartSelector from './PartSelector';
|
||||
import PlaySpeedSelector from './PlaySpeedSelector';
|
||||
|
||||
export default class Explorer extends Component {
|
||||
static propTypes = {
|
||||
|
@ -66,20 +66,20 @@ export default class Explorer extends Component {
|
|||
}
|
||||
|
||||
componentWillMount() {
|
||||
document.addEventListener("keydown", this._onKeyDown);
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener("keydown", this._onKeyDown);
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
}
|
||||
|
||||
clipSegment(segment, segmentIndices, nextMessage) {
|
||||
if (segment.length === 2) {
|
||||
const segmentStartIdx = nextMessage.entries.findIndex(
|
||||
e => e.relTime >= segment[0]
|
||||
(e) => e.relTime >= segment[0]
|
||||
);
|
||||
let segmentEndIdx = nextMessage.entries.findIndex(
|
||||
e => e.relTime >= segment[1]
|
||||
(e) => e.relTime >= segment[1]
|
||||
);
|
||||
if (segmentStartIdx !== -1) {
|
||||
if (segmentEndIdx === -1) {
|
||||
|
@ -119,32 +119,30 @@ export default class Explorer extends Component {
|
|||
|
||||
// remove plottedSignals that no longer exist
|
||||
plottedSignals = plottedSignals
|
||||
.map(plot =>
|
||||
plot.filter(({ messageId, signalUid }, index) => {
|
||||
const messageExists = !!nextProps.messages[messageId];
|
||||
let signalExists = true;
|
||||
if (messageExists) {
|
||||
signalExists = Object.values(
|
||||
nextProps.messages[messageId].frame.signals
|
||||
).some(signal => signal.uid === signalUid);
|
||||
}
|
||||
.map((plot) => plot.filter(({ messageId, signalUid }, index) => {
|
||||
const messageExists = !!nextProps.messages[messageId];
|
||||
let signalExists = true;
|
||||
if (messageExists) {
|
||||
signalExists = Object.values(
|
||||
nextProps.messages[messageId].frame.signals
|
||||
).some((signal) => signal.uid === signalUid);
|
||||
}
|
||||
|
||||
return messageExists && signalExists;
|
||||
})
|
||||
)
|
||||
.filter(plot => plot.length > 0);
|
||||
return messageExists && signalExists;
|
||||
}))
|
||||
.filter((plot) => plot.length > 0);
|
||||
|
||||
this.setState({ plottedSignals });
|
||||
|
||||
if (
|
||||
nextProps.selectedMessage &&
|
||||
nextProps.selectedMessage !== this.props.selectedMessage
|
||||
nextProps.selectedMessage
|
||||
&& nextProps.selectedMessage !== this.props.selectedMessage
|
||||
) {
|
||||
// Update segment and seek state
|
||||
// by finding a entry indices
|
||||
// corresponding to old message segment/seek times.
|
||||
|
||||
let { segment, segmentIndices } = this.clipSegment(
|
||||
const { segment, segmentIndices } = this.clipSegment(
|
||||
this.state.segment,
|
||||
this.state.segmentIndices,
|
||||
nextMessage
|
||||
|
@ -169,11 +167,11 @@ export default class Explorer extends Component {
|
|||
}
|
||||
|
||||
if (
|
||||
nextMessage &&
|
||||
curMessage &&
|
||||
nextMessage.entries.length !== curMessage.entries.length
|
||||
nextMessage
|
||||
&& curMessage
|
||||
&& nextMessage.entries.length !== curMessage.entries.length
|
||||
) {
|
||||
let { segment, segmentIndices } = this.clipSegment(
|
||||
const { segment, segmentIndices } = this.clipSegment(
|
||||
this.state.segment,
|
||||
this.state.segmentIndices,
|
||||
nextMessage
|
||||
|
@ -193,20 +191,21 @@ export default class Explorer extends Component {
|
|||
const { routeStartTime, currentParts } = this.props;
|
||||
|
||||
if (routeStartTime) {
|
||||
const partStartOffset = currentParts[0] * 60,
|
||||
partEndOffset = (currentParts[1] + 1) * 60;
|
||||
const partStartOffset = currentParts[0] * 60;
|
||||
const partEndOffset = (currentParts[1] + 1) * 60;
|
||||
|
||||
const windowStartTime = routeStartTime
|
||||
.clone()
|
||||
.add(partStartOffset, "s")
|
||||
.format("HH:mm:ss");
|
||||
.add(partStartOffset, 's')
|
||||
.format('HH:mm:ss');
|
||||
const windowEndTime = routeStartTime
|
||||
.clone()
|
||||
.add(partEndOffset, "s")
|
||||
.format("HH:mm:ss");
|
||||
.add(partEndOffset, 's')
|
||||
.format('HH:mm:ss');
|
||||
|
||||
return `${windowStartTime} - ${windowEndTime}`;
|
||||
} else return "";
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
onSignalPlotPressed(messageId, signalUid) {
|
||||
|
@ -220,13 +219,10 @@ export default class Explorer extends Component {
|
|||
onSignalUnplotPressed(messageId, signalUid) {
|
||||
const { plottedSignals } = this.state;
|
||||
const newPlottedSignals = plottedSignals
|
||||
.map(plot =>
|
||||
plot.filter(
|
||||
signal =>
|
||||
!(signal.messageId === messageId && signal.signalUid === signalUid)
|
||||
)
|
||||
)
|
||||
.filter(plot => plot.length > 0);
|
||||
.map((plot) => plot.filter(
|
||||
(signal) => !(signal.messageId === messageId && signal.signalUid === signalUid)
|
||||
))
|
||||
.filter((plot) => plot.length > 0);
|
||||
|
||||
this.setState({ plottedSignals: newPlottedSignals });
|
||||
}
|
||||
|
@ -237,8 +233,8 @@ export default class Explorer extends Component {
|
|||
|
||||
// console.log(this.state.segment, '->', segment, segmentIndices);
|
||||
if (
|
||||
segment[0] === this.props.currentParts[0] * 60 &&
|
||||
segment[1] === (this.props.currentParts[1] + 1) * 60
|
||||
segment[0] === this.props.currentParts[0] * 60
|
||||
&& segment[1] === (this.props.currentParts[1] + 1) * 60
|
||||
) {
|
||||
segment = [];
|
||||
segmentIndices = [];
|
||||
|
@ -297,14 +293,13 @@ export default class Explorer extends Component {
|
|||
}
|
||||
}
|
||||
return segmentIndices[1];
|
||||
} else {
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
if (entries[i].relTime >= time) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return entries.length - 1;
|
||||
}
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
if (entries[i].relTime >= time) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return entries.length - 1;
|
||||
}
|
||||
|
||||
onUserSeek(time) {
|
||||
|
@ -377,24 +372,20 @@ export default class Explorer extends Component {
|
|||
selectedMessagePlottedSignalUids() {
|
||||
const { plottedSignals } = this.state;
|
||||
return plottedSignals
|
||||
.map(plot =>
|
||||
plot
|
||||
.filter(
|
||||
({ messageId, signalUid }) =>
|
||||
messageId === this.props.selectedMessage
|
||||
)
|
||||
.map(({ signalUid }) => signalUid)
|
||||
)
|
||||
.map((plot) => plot
|
||||
.filter(
|
||||
({ messageId, signalUid }) => messageId === this.props.selectedMessage
|
||||
)
|
||||
.map(({ signalUid }) => signalUid))
|
||||
.reduce((arr, signalUid) => arr.concat(signalUid), []);
|
||||
}
|
||||
|
||||
renderExplorerSignals() {
|
||||
const selectedMessageKey = this.props.selectedMessage;
|
||||
const selectedMessage = this.props.messages[selectedMessageKey];
|
||||
const selectedMessageName =
|
||||
selectedMessage.frame !== undefined
|
||||
? selectedMessage.frame.name
|
||||
: "undefined";
|
||||
const selectedMessageName = selectedMessage.frame !== undefined
|
||||
? selectedMessage.frame.name
|
||||
: 'undefined';
|
||||
return (
|
||||
<div className="cabana-explorer-signals-wrapper">
|
||||
<div className="cabana-explorer-signals-header">
|
||||
|
@ -405,9 +396,7 @@ export default class Explorer extends Component {
|
|||
<div className="cabana-explorer-signals-header-action">
|
||||
<button
|
||||
className="button--small"
|
||||
onClick={() =>
|
||||
this.props.showEditMessageModal(selectedMessageKey)
|
||||
}
|
||||
onClick={() => this.props.showEditMessageModal(selectedMessageKey)}
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
@ -448,25 +437,19 @@ export default class Explorer extends Component {
|
|||
}
|
||||
|
||||
mergePlots({ fromPlot, toPlot }) {
|
||||
let { plottedSignals } = this.state;
|
||||
const { plottedSignals } = this.state;
|
||||
|
||||
// remove fromPlot from plottedSignals
|
||||
const fromPlotIdx = plottedSignals.findIndex(plot =>
|
||||
plot.some(
|
||||
signal =>
|
||||
signal.signalUid === fromPlot.signalUid &&
|
||||
signal.messageId === fromPlot.messageId
|
||||
)
|
||||
);
|
||||
const fromPlotIdx = plottedSignals.findIndex((plot) => plot.some(
|
||||
(signal) => signal.signalUid === fromPlot.signalUid
|
||||
&& signal.messageId === fromPlot.messageId
|
||||
));
|
||||
plottedSignals.splice(fromPlotIdx, 1);
|
||||
|
||||
const toPlotIdx = plottedSignals.findIndex(plot =>
|
||||
plot.some(
|
||||
signal =>
|
||||
signal.signalUid === toPlot.signalUid &&
|
||||
signal.messageId === toPlot.messageId
|
||||
)
|
||||
);
|
||||
const toPlotIdx = plottedSignals.findIndex((plot) => plot.some(
|
||||
(signal) => signal.signalUid === toPlot.signalUid
|
||||
&& signal.messageId === toPlot.messageId
|
||||
));
|
||||
plottedSignals[toPlotIdx] = [fromPlot, toPlot];
|
||||
|
||||
this.setState({ plottedSignals });
|
||||
|
@ -474,7 +457,7 @@ export default class Explorer extends Component {
|
|||
|
||||
render() {
|
||||
const signalsExpandedClass = this.state.shouldShowAddSignal
|
||||
? "is-expanded"
|
||||
? 'is-expanded'
|
||||
: null;
|
||||
|
||||
let graphSegment = this.state.segment;
|
||||
|
@ -487,7 +470,7 @@ export default class Explorer extends Component {
|
|||
|
||||
return (
|
||||
<div className="cabana-explorer">
|
||||
<div className={cx("cabana-explorer-signals", signalsExpandedClass)}>
|
||||
<div className={cx('cabana-explorer-signals', signalsExpandedClass)}>
|
||||
{this.props.messages[this.props.selectedMessage]
|
||||
? this.renderExplorerSignals()
|
||||
: this.renderSelectMessagePrompt()}
|
||||
|
@ -522,7 +505,7 @@ export default class Explorer extends Component {
|
|||
) : null}
|
||||
{this.state.segment.length > 0 ? (
|
||||
<div
|
||||
className={"cabana-explorer-visuals-segmentreset"}
|
||||
className="cabana-explorer-visuals-segmentreset"
|
||||
onClick={() => {
|
||||
this.resetSegment();
|
||||
}}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { Component } from "react";
|
||||
import cx from "classnames";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import cx from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import OpenDbc from "../api/OpenDbc";
|
||||
import OpenDbc from '../api/OpenDbc';
|
||||
|
||||
export default class GithubDbcList extends Component {
|
||||
static propTypes = {
|
||||
|
@ -17,7 +17,7 @@ export default class GithubDbcList extends Component {
|
|||
this.state = {
|
||||
paths: [],
|
||||
selectedPath: null,
|
||||
pathQuery: ""
|
||||
pathQuery: ''
|
||||
};
|
||||
|
||||
this.updatePathQuery = this.updatePathQuery.bind(this);
|
||||
|
@ -25,15 +25,15 @@ export default class GithubDbcList extends Component {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.repo !== this.props.repo) {
|
||||
this.props.openDbcClient.list(nextProps.repo).then(paths => {
|
||||
this.props.openDbcClient.list(nextProps.repo).then((paths) => {
|
||||
this.setState({ paths, selectedPath: null });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.openDbcClient.list(this.props.repo).then(paths => {
|
||||
paths = paths.filter(path => path.indexOf(".dbc") !== -1);
|
||||
this.props.openDbcClient.list(this.props.repo).then((paths) => {
|
||||
paths = paths.filter((path) => path.indexOf('.dbc') !== -1);
|
||||
this.setState({ paths });
|
||||
});
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ export default class GithubDbcList extends Component {
|
|||
this.setState({ selectedPath: path });
|
||||
this.props.openDbcClient
|
||||
.getDbcContents(path, this.props.repo)
|
||||
.then(dbcContents => {
|
||||
.then((dbcContents) => {
|
||||
this.props.onDbcLoaded(path, dbcContents);
|
||||
});
|
||||
}
|
||||
|
@ -72,24 +72,21 @@ export default class GithubDbcList extends Component {
|
|||
<div className="cabana-dbc-list-files">
|
||||
{this.state.paths
|
||||
.filter(
|
||||
p =>
|
||||
(this.state.pathQuery === "") | p.includes(this.state.pathQuery)
|
||||
(p) => (this.state.pathQuery === '') | p.includes(this.state.pathQuery)
|
||||
)
|
||||
.map(path => {
|
||||
return (
|
||||
<div
|
||||
className={cx("cabana-dbc-list-file", {
|
||||
"is-selected": this.state.selectedPath === path
|
||||
})}
|
||||
onClick={() => {
|
||||
this.selectPath(path);
|
||||
}}
|
||||
key={path}
|
||||
>
|
||||
<span>{path}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
.map((path) => (
|
||||
<div
|
||||
className={cx('cabana-dbc-list-file', {
|
||||
'is-selected': this.state.selectedPath === path
|
||||
})}
|
||||
onClick={() => {
|
||||
this.selectPath(path);
|
||||
}}
|
||||
key={path}
|
||||
>
|
||||
<span>{path}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Hls from "hls.js";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Hls from 'hls.js';
|
||||
|
||||
export default class HLS extends Component {
|
||||
static propTypes = {
|
||||
|
@ -26,8 +26,8 @@ export default class HLS extends Component {
|
|||
}
|
||||
if (nextProps.playing) {
|
||||
if (
|
||||
this.videoElement &&
|
||||
(this.videoElement.paused || this.videoElement.currentTime < 0.01)
|
||||
this.videoElement
|
||||
&& (this.videoElement.paused || this.videoElement.currentTime < 0.01)
|
||||
) {
|
||||
this.videoElement.play();
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ export default class HLS extends Component {
|
|||
// legacy outer scope variable. Revisit this to see if putting in state
|
||||
// makes more sense
|
||||
shouldInitVideoTime = true;
|
||||
|
||||
onSeeked = () => {
|
||||
if (!this.props.playing) {
|
||||
if (this.shouldInitVideoTime) {
|
||||
|
@ -84,7 +85,7 @@ export default class HLS extends Component {
|
|||
onClick={this.props.onClick}
|
||||
>
|
||||
<video
|
||||
ref={video => {
|
||||
ref={(video) => {
|
||||
this.videoElement = video;
|
||||
}}
|
||||
autoPlay={this.props.playing}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import cx from "classnames";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
|
||||
import DBC from "../models/can/dbc";
|
||||
import OpenDbc from "../api/OpenDbc";
|
||||
import Modal from "./Modals/baseModal";
|
||||
import GithubDbcList from "./GithubDbcList";
|
||||
import DbcUpload from "./DbcUpload";
|
||||
import DBC from '../models/can/dbc';
|
||||
import OpenDbc from '../api/OpenDbc';
|
||||
import Modal from './Modals/baseModal';
|
||||
import GithubDbcList from './GithubDbcList';
|
||||
import DbcUpload from './DbcUpload';
|
||||
|
||||
export default class LoadDbcModal extends Component {
|
||||
static propTypes = {
|
||||
|
@ -19,8 +19,8 @@ export default class LoadDbcModal extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
tab: "OpenDBC",
|
||||
tabs: ["OpenDBC", "GitHub", "Upload"],
|
||||
tab: 'OpenDBC',
|
||||
tabs: ['OpenDBC', 'GitHub', 'Upload'],
|
||||
dbc: null,
|
||||
dbcSource: null,
|
||||
userOpenDbcRepo: null
|
||||
|
@ -34,7 +34,7 @@ export default class LoadDbcModal extends Component {
|
|||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.openDbcClient.getUserOpenDbcFork().then(userOpenDbcRepo => {
|
||||
this.props.openDbcClient.getUserOpenDbcFork().then((userOpenDbcRepo) => {
|
||||
this.setState({ userOpenDbcRepo });
|
||||
});
|
||||
}
|
||||
|
@ -54,26 +54,24 @@ export default class LoadDbcModal extends Component {
|
|||
renderTabNavigation() {
|
||||
return (
|
||||
<div className="cabana-tabs-navigation">
|
||||
{this.state.tabs.map(tab => {
|
||||
return (
|
||||
<a
|
||||
className={cx({ "is-active": this.state.tab === tab })}
|
||||
onClick={() => {
|
||||
this.setState({ tab });
|
||||
}}
|
||||
key={tab}
|
||||
>
|
||||
<span>{tab}</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
{this.state.tabs.map((tab) => (
|
||||
<a
|
||||
className={cx({ 'is-active': this.state.tab === tab })}
|
||||
onClick={() => {
|
||||
this.setState({ tab });
|
||||
}}
|
||||
key={tab}
|
||||
>
|
||||
<span>{tab}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderTabContent() {
|
||||
const { tab } = this.state;
|
||||
if (tab === "OpenDBC") {
|
||||
if (tab === 'OpenDBC') {
|
||||
return (
|
||||
<GithubDbcList
|
||||
onDbcLoaded={this.onDbcLoaded}
|
||||
|
@ -81,21 +79,23 @@ export default class LoadDbcModal extends Component {
|
|||
openDbcClient={this.props.openDbcClient}
|
||||
/>
|
||||
);
|
||||
} else if (tab === "GitHub") {
|
||||
}
|
||||
if (tab === 'GitHub') {
|
||||
if (!this.props.openDbcClient.hasAuth()) {
|
||||
return this.props.loginWithGithub;
|
||||
} else if (this.state.userOpenDbcRepo === null) {
|
||||
return <div>Fork it</div>;
|
||||
} else {
|
||||
return (
|
||||
<GithubDbcList
|
||||
onDbcLoaded={this.onDbcLoaded}
|
||||
repo={this.state.userOpenDbcRepo}
|
||||
openDbcClient={this.props.openDbcClient}
|
||||
/>
|
||||
);
|
||||
}
|
||||
} else if (tab === "Upload") {
|
||||
if (this.state.userOpenDbcRepo === null) {
|
||||
return <div>Fork it</div>;
|
||||
}
|
||||
return (
|
||||
<GithubDbcList
|
||||
onDbcLoaded={this.onDbcLoaded}
|
||||
repo={this.state.userOpenDbcRepo}
|
||||
openDbcClient={this.props.openDbcClient}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (tab === 'Upload') {
|
||||
return <DbcUpload onDbcLoaded={this.onDbcLoaded} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import styled, { keyframes } from "react-emotion";
|
||||
import styled, { keyframes } from 'react-emotion';
|
||||
|
||||
const frames = keyframes`
|
||||
0% {
|
||||
|
@ -8,10 +8,10 @@ const frames = keyframes`
|
|||
transform: translateX(-400px)
|
||||
}
|
||||
`;
|
||||
const animationColor1 = "rgba(74, 242, 161, 1.00)";
|
||||
const animationColor2 = "rgba(140, 169, 197, 1.00)";
|
||||
const animationColor1 = 'rgba(74, 242, 161, 1.00)';
|
||||
const animationColor2 = 'rgba(140, 169, 197, 1.00)';
|
||||
|
||||
export default styled("div")`
|
||||
export default styled('div')`
|
||||
display: block;
|
||||
animation-name: ${frames};
|
||||
animation-duration: 2s;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class MessageBytes extends Component {
|
||||
static propTypes = {
|
||||
|
@ -23,22 +23,20 @@ export default class MessageBytes extends Component {
|
|||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
if (nextProps.live) {
|
||||
const nextLastEntry =
|
||||
nextProps.message.entries[nextProps.message.entries.length - 1];
|
||||
const nextLastEntry = nextProps.message.entries[nextProps.message.entries.length - 1];
|
||||
const curLastEntry = this.props.message.entries[
|
||||
this.props.message.entries.length - 1
|
||||
];
|
||||
|
||||
return nextLastEntry.hexData !== curLastEntry.hexData;
|
||||
} else {
|
||||
return nextProps.seekTime !== this.props.seekTime;
|
||||
}
|
||||
return nextProps.seekTime !== this.props.seekTime;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
this.props.seekIndex !== nextProps.seekIndex ||
|
||||
frameForTime(this.props.seekTime) !== frameForTime(nextProps.seekTime)
|
||||
this.props.seekIndex !== nextProps.seekIndex
|
||||
|| frameForTime(this.props.seekTime) !== frameForTime(nextProps.seekTime)
|
||||
) {
|
||||
this.updateCanvas(nextProps);
|
||||
}
|
||||
|
@ -66,7 +64,7 @@ export default class MessageBytes extends Component {
|
|||
// TODO this can be faster with binary search, not currently a bottleneck though.
|
||||
|
||||
mostRecentMessageIndex = message.entries.findIndex(
|
||||
e => e.relTime >= seekTime
|
||||
(e) => e.relTime >= seekTime
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -92,7 +90,7 @@ export default class MessageBytes extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
const ctx = this.canvas.getContext("2d");
|
||||
const ctx = this.canvas.getContext('2d');
|
||||
// ctx.clearRect(0, 0, 180, 15);
|
||||
|
||||
for (let i = 0; i < message.byteStateChangeCounts.length; ++i) {
|
||||
|
@ -101,12 +99,12 @@ export default class MessageBytes extends Component {
|
|||
|
||||
ctx.fillRect(i * 20, 0, 20, 15);
|
||||
|
||||
ctx.font = "12px Courier";
|
||||
ctx.fillStyle = "white";
|
||||
ctx.font = '12px Courier';
|
||||
ctx.fillStyle = 'white';
|
||||
if (hexData) {
|
||||
ctx.fillText(hexData, i * 20 + 2, 12);
|
||||
} else {
|
||||
ctx.fillText("-", i * 20 + 7, 12);
|
||||
ctx.fillText('-', i * 20 + 7, 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +121,7 @@ export default class MessageBytes extends Component {
|
|||
this.canvas = ref;
|
||||
this.canvas.width = 160 * window.devicePixelRatio;
|
||||
this.canvas.height = 15 * window.devicePixelRatio;
|
||||
const ctx = this.canvas.getContext("2d");
|
||||
const ctx = this.canvas.getContext('2d');
|
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
import cx from "classnames";
|
||||
import PropTypes from "prop-types";
|
||||
import Clipboard from "clipboard";
|
||||
import React, { Component } from 'react';
|
||||
import cx from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import Clipboard from 'clipboard';
|
||||
|
||||
import MessageBytes from "./MessageBytes";
|
||||
const { ckmeans } = require("simple-statistics");
|
||||
import MessageBytes from './MessageBytes';
|
||||
|
||||
const { ckmeans } = require('simple-statistics');
|
||||
|
||||
export default class Meta extends Component {
|
||||
static propTypes = {
|
||||
|
@ -44,7 +45,7 @@ export default class Meta extends Component {
|
|||
const { dbcLastSaved } = props;
|
||||
|
||||
this.state = {
|
||||
filterText: "Filter",
|
||||
filterText: 'Filter',
|
||||
lastSaved:
|
||||
dbcLastSaved !== null ? this.props.dbcLastSaved.fromNow() : null,
|
||||
hoveredMessages: [],
|
||||
|
@ -67,25 +68,25 @@ export default class Meta extends Component {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.lastSaved !== this.props.lastSaved &&
|
||||
typeof nextProps === "object"
|
||||
nextProps.lastSaved !== this.props.lastSaved
|
||||
&& typeof nextProps === 'object'
|
||||
) {
|
||||
this.setState({ lastSaved: nextProps.dbcLastSaved.fromNow() });
|
||||
}
|
||||
|
||||
const nextMsgKeys = Object.keys(nextProps.messages);
|
||||
if (
|
||||
JSON.stringify(nextMsgKeys) !==
|
||||
JSON.stringify(Object.keys(this.props.messages))
|
||||
JSON.stringify(nextMsgKeys)
|
||||
!== JSON.stringify(Object.keys(this.props.messages))
|
||||
) {
|
||||
const orderedMessageKeys = this.sortMessages(nextProps.messages);
|
||||
this.setState({ hoveredMessages: [], orderedMessageKeys });
|
||||
} else if (
|
||||
this.state.orderedMessageKeys.length === 0 ||
|
||||
(!this.props.live &&
|
||||
this.props.messages &&
|
||||
nextProps.messages &&
|
||||
this.byteCountsDidUpdate(this.props.messages, nextProps.messages))
|
||||
this.state.orderedMessageKeys.length === 0
|
||||
|| (!this.props.live
|
||||
&& this.props.messages
|
||||
&& nextProps.messages
|
||||
&& this.byteCountsDidUpdate(this.props.messages, nextProps.messages))
|
||||
) {
|
||||
const orderedMessageKeys = this.sortMessages(nextProps.messages);
|
||||
this.setState({ orderedMessageKeys });
|
||||
|
@ -94,9 +95,8 @@ export default class Meta extends Component {
|
|||
|
||||
byteCountsDidUpdate(prevMessages, nextMessages) {
|
||||
return Object.entries(nextMessages).some(
|
||||
([msgId, msg]) =>
|
||||
JSON.stringify(msg.byteStateChangeCounts) !==
|
||||
JSON.stringify(prevMessages[msgId].byteStateChangeCounts)
|
||||
([msgId, msg]) => JSON.stringify(msg.byteStateChangeCounts)
|
||||
!== JSON.stringify(prevMessages[msgId].byteStateChangeCounts)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -121,27 +121,22 @@ export default class Meta extends Component {
|
|||
{}
|
||||
);
|
||||
|
||||
const entryCounts = Object.keys(messagesByEntryCount).map(count =>
|
||||
parseInt(count, 10)
|
||||
);
|
||||
const entryCounts = Object.keys(messagesByEntryCount).map((count) => parseInt(count, 10));
|
||||
const binnedEntryCounts = ckmeans(
|
||||
entryCounts,
|
||||
Math.min(entryCounts.length, 10)
|
||||
);
|
||||
const sortedKeys = binnedEntryCounts
|
||||
.map(bin =>
|
||||
bin
|
||||
.map(entryCount => messagesByEntryCount[entryCount.toString()])
|
||||
.reduce((messages, partial) => messages.concat(partial), [])
|
||||
.sort((msg1, msg2) => {
|
||||
if (msg1.address < msg2.address) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
})
|
||||
.map(msg => msg.id)
|
||||
)
|
||||
.map((bin) => bin
|
||||
.map((entryCount) => messagesByEntryCount[entryCount.toString()])
|
||||
.reduce((messages, partial) => messages.concat(partial), [])
|
||||
.sort((msg1, msg2) => {
|
||||
if (msg1.address < msg2.address) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
})
|
||||
.map((msg) => msg.id))
|
||||
.reduce((keys, bin) => keys.concat(bin), [])
|
||||
.reverse();
|
||||
|
||||
|
@ -156,20 +151,20 @@ export default class Meta extends Component {
|
|||
|
||||
onFilterChanged(e) {
|
||||
let val = e.target.value;
|
||||
if (val.trim() === "Filter") val = "";
|
||||
if (val.trim() === 'Filter') val = '';
|
||||
|
||||
this.setState({ filterText: val });
|
||||
}
|
||||
|
||||
onFilterFocus(e) {
|
||||
if (this.state.filterText.trim() === "Filter") {
|
||||
this.setState({ filterText: "" });
|
||||
if (this.state.filterText.trim() === 'Filter') {
|
||||
this.setState({ filterText: '' });
|
||||
}
|
||||
}
|
||||
|
||||
onFilterUnfocus(e) {
|
||||
if (this.state.filterText.trim() === "") {
|
||||
this.setState({ filterText: "Filter" });
|
||||
if (this.state.filterText.trim() === '') {
|
||||
this.setState({ filterText: 'Filter' });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,13 +173,13 @@ export default class Meta extends Component {
|
|||
return;
|
||||
}
|
||||
const { filterText } = this.state;
|
||||
const msgName = msg.frame ? msg.frame.name : "";
|
||||
const msgName = msg.frame ? msg.frame.name : '';
|
||||
|
||||
return (
|
||||
filterText === "Filter" ||
|
||||
filterText === "" ||
|
||||
msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1 ||
|
||||
msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|
||||
filterText === 'Filter'
|
||||
|| filterText === ''
|
||||
|| msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|
||||
|| msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -193,13 +188,13 @@ export default class Meta extends Component {
|
|||
return;
|
||||
}
|
||||
const { filterText } = this.state;
|
||||
const msgName = msg.frame ? msg.frame.name : "";
|
||||
const msgName = msg.frame ? msg.frame.name : '';
|
||||
|
||||
return (
|
||||
filterText === "Filter" ||
|
||||
filterText === "" ||
|
||||
msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1 ||
|
||||
msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|
||||
filterText === 'Filter'
|
||||
|| filterText === ''
|
||||
|| msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|
||||
|| msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -209,7 +204,7 @@ export default class Meta extends Component {
|
|||
}
|
||||
|
||||
onMessageHover(key) {
|
||||
let { hoveredMessages } = this.state;
|
||||
const { hoveredMessages } = this.state;
|
||||
if (hoveredMessages.indexOf(key) !== -1) return;
|
||||
|
||||
hoveredMessages.push(key);
|
||||
|
@ -218,13 +213,13 @@ export default class Meta extends Component {
|
|||
|
||||
onMessageHoverEnd(key) {
|
||||
let { hoveredMessages } = this.state;
|
||||
hoveredMessages = hoveredMessages.filter(m => m !== key);
|
||||
hoveredMessages = hoveredMessages.filter((m) => m !== key);
|
||||
this.setState({ hoveredMessages });
|
||||
}
|
||||
|
||||
onMsgRemoveClick(key) {
|
||||
let { selectedMessages } = this.state;
|
||||
selectedMessages = selectedMessages.filter(m => m !== key);
|
||||
selectedMessages = selectedMessages.filter((m) => m !== key);
|
||||
this.props.onMessageUnselected(key);
|
||||
this.setState({ selectedMessages });
|
||||
}
|
||||
|
@ -241,12 +236,12 @@ export default class Meta extends Component {
|
|||
orderedMessages() {
|
||||
const { orderedMessageKeys } = this.state;
|
||||
const { messages } = this.props;
|
||||
return orderedMessageKeys.map(key => messages[key]);
|
||||
return orderedMessageKeys.map((key) => messages[key]);
|
||||
}
|
||||
|
||||
selectedMessageClass(messageId) {
|
||||
return this.props.selectedMessages.includes(messageId)
|
||||
? "is-selected"
|
||||
? 'is-selected'
|
||||
: null;
|
||||
}
|
||||
|
||||
|
@ -258,17 +253,17 @@ export default class Meta extends Component {
|
|||
}}
|
||||
key={msg.id}
|
||||
className={cx(
|
||||
"cabana-meta-messages-list-item",
|
||||
'cabana-meta-messages-list-item',
|
||||
this.selectedMessageClass(msg.id)
|
||||
)}
|
||||
>
|
||||
{msg.isLogEvent ? (
|
||||
<td colSpan="2">{msg.id}</td>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
<td>{msg.frame ? msg.frame.name : "untitled"}</td>
|
||||
<>
|
||||
<td>{msg.frame ? msg.frame.name : 'untitled'}</td>
|
||||
<td>{msg.id}</td>
|
||||
</React.Fragment>
|
||||
</>
|
||||
)}
|
||||
<td>{msg.entries.length}</td>
|
||||
<td>
|
||||
|
@ -303,10 +298,10 @@ export default class Meta extends Component {
|
|||
return <p>Loading messages...</p>;
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<>
|
||||
<table cellPadding="5">
|
||||
{this.state.showLogEvents && (
|
||||
<React.Fragment>
|
||||
<>
|
||||
<thead>
|
||||
<tr>
|
||||
<td colSpan="2">Name</td>
|
||||
|
@ -322,7 +317,7 @@ export default class Meta extends Component {
|
|||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</React.Fragment>
|
||||
</>
|
||||
)}
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -334,7 +329,7 @@ export default class Meta extends Component {
|
|||
</thead>
|
||||
<tbody>{this.renderCanMessages()}</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -342,13 +337,14 @@ export default class Meta extends Component {
|
|||
try {
|
||||
// eslint-disable-next-line
|
||||
"serviceWorker" in navigator &&
|
||||
!!new ReadableStream() &&
|
||||
!!new WritableStream(); // eslint-disable-line no-undef
|
||||
return "saveable";
|
||||
!!new ReadableStream()
|
||||
&& !!new WritableStream(); // eslint-disable-line no-undef
|
||||
return 'saveable';
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="cabana-meta">
|
||||
|
@ -361,7 +357,10 @@ export default class Meta extends Component {
|
|||
</strong>
|
||||
{this.props.dbcLastSaved !== null ? (
|
||||
<div className="cabana-meta-header-last-saved">
|
||||
<p>Last saved: {this.lastSavedPretty()}</p>
|
||||
<p>
|
||||
Last saved:
|
||||
{this.lastSavedPretty()}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
<div className={`cabana-meta-header-actions ${this.saveable()}`}>
|
||||
|
@ -378,12 +377,12 @@ export default class Meta extends Component {
|
|||
className="cabana-meta-header-action special-wide"
|
||||
data-clipboard-text={this.props.shareUrl}
|
||||
data-clipboard-action="copy"
|
||||
ref={ref => (ref ? new Clipboard(ref) : null)}
|
||||
ref={(ref) => (ref ? new Clipboard(ref) : null)}
|
||||
>
|
||||
<a
|
||||
className="button"
|
||||
href={this.props.shareUrl}
|
||||
onClick={e => e.preventDefault()}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
Copy Share Link
|
||||
</a>
|
||||
|
@ -398,8 +397,8 @@ export default class Meta extends Component {
|
|||
<div className="cabana-meta-messages-header">
|
||||
<div
|
||||
style={{
|
||||
display: "inline-block",
|
||||
float: "right"
|
||||
display: 'inline-block',
|
||||
float: 'right'
|
||||
}}
|
||||
>
|
||||
<h5 className="t-capline">
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Moment from "moment";
|
||||
import _ from "lodash";
|
||||
import cx from "classnames";
|
||||
import CommaAuth from "@commaai/my-comma-auth";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import cx from 'classnames';
|
||||
import CommaAuth from '@commaai/my-comma-auth';
|
||||
|
||||
import { EXPLORER_URL } from "../../config";
|
||||
import Modal from "../Modals/baseModal";
|
||||
import { EXPLORER_URL } from '../../config';
|
||||
import Modal from './baseModal';
|
||||
|
||||
export default class OnboardingModal extends Component {
|
||||
static propTypes = {
|
||||
|
@ -15,8 +15,8 @@ export default class OnboardingModal extends Component {
|
|||
};
|
||||
|
||||
static instructionalImages = {
|
||||
step2: require("../../images/webusb-enable-experimental-features.png"),
|
||||
step3: require("../../images/webusb-enable-webusb.png")
|
||||
step2: require('../../images/webusb-enable-experimental-features.png'),
|
||||
step3: require('../../images/webusb-enable-webusb.png')
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
@ -66,7 +66,8 @@ export default class OnboardingModal extends Component {
|
|||
</a>
|
||||
</p>
|
||||
);
|
||||
} else if (!pandaConnected && attemptingPandaConnection) {
|
||||
}
|
||||
if (!pandaConnected && attemptingPandaConnection) {
|
||||
return (
|
||||
<p>
|
||||
<i className="fa fa-spinner animate-spin" />
|
||||
|
@ -87,8 +88,8 @@ export default class OnboardingModal extends Component {
|
|||
<i className="fa fa-video-camera" />
|
||||
<strong>
|
||||
{CommaAuth.isAuthenticated()
|
||||
? "Find a drive in Explorer"
|
||||
: "Log in with Explorer"}
|
||||
? 'Find a drive in Explorer'
|
||||
: 'Log in with Explorer'}
|
||||
</strong>
|
||||
<sup>Click "View CAN Data" while replaying a drive</sup>
|
||||
</button>
|
||||
|
@ -101,17 +102,19 @@ export default class OnboardingModal extends Component {
|
|||
<div className="cabana-onboarding-mode">{this.renderLogin()}</div>
|
||||
<div className="cabana-onboarding-mode">
|
||||
<button
|
||||
className={cx("button--secondary button--kiosk", {
|
||||
"is-disabled":
|
||||
!this.state.webUsbEnabled ||
|
||||
this.props.attemptingPandaConnection
|
||||
className={cx('button--secondary button--kiosk', {
|
||||
'is-disabled':
|
||||
!this.state.webUsbEnabled
|
||||
|| this.props.attemptingPandaConnection
|
||||
})}
|
||||
onClick={this.attemptPandaConnection}
|
||||
>
|
||||
<i className="fa fa-bolt" />
|
||||
<strong>Launch Realtime Streaming</strong>
|
||||
<sup>
|
||||
Interactively stream car data over USB with <em>panda</em>
|
||||
Interactively stream car data over USB with
|
||||
{' '}
|
||||
<em>panda</em>
|
||||
</sup>
|
||||
{this.renderPandaEligibility()}
|
||||
</button>
|
||||
|
@ -147,7 +150,7 @@ export default class OnboardingModal extends Component {
|
|||
<strong>Enable Experimental Platform features:</strong>
|
||||
</p>
|
||||
<img
|
||||
alt={"Screenshot of Google Chrome Experimental Platform features"}
|
||||
alt="Screenshot of Google Chrome Experimental Platform features"
|
||||
src={OnboardingModal.instructionalImages.step2}
|
||||
/>
|
||||
</li>
|
||||
|
@ -156,7 +159,7 @@ export default class OnboardingModal extends Component {
|
|||
<strong>Enable WebUSB:</strong>
|
||||
</p>
|
||||
<img
|
||||
alt={"Screenshot of Google Chrome enable WebUSB"}
|
||||
alt="Screenshot of Google Chrome enable WebUSB"
|
||||
src={OnboardingModal.instructionalImages.step3}
|
||||
/>
|
||||
</li>
|
||||
|
@ -175,23 +178,25 @@ export default class OnboardingModal extends Component {
|
|||
renderModalContent() {
|
||||
if (this.state.viewingUsbInstructions) {
|
||||
return this.renderUsbInstructions();
|
||||
} else {
|
||||
return this.renderOnboardingOptions();
|
||||
}
|
||||
return this.renderOnboardingOptions();
|
||||
}
|
||||
|
||||
renderModalFooter() {
|
||||
return (
|
||||
<p>
|
||||
<span>
|
||||
Don't have a{" "}
|
||||
Don't have a
|
||||
{' '}
|
||||
<a
|
||||
href="https://panda.comma.ai"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
panda
|
||||
</a>?{" "}
|
||||
</a>
|
||||
?
|
||||
{' '}
|
||||
</span>
|
||||
<span>
|
||||
<a
|
||||
|
@ -200,10 +205,14 @@ export default class OnboardingModal extends Component {
|
|||
rel="noopener noreferrer"
|
||||
>
|
||||
Get one here
|
||||
</a>{" "}
|
||||
</a>
|
||||
{' '}
|
||||
</span>
|
||||
<span>
|
||||
or <a href={`${window.location.href}?demo=1`}>try the demo</a>.
|
||||
or
|
||||
{' '}
|
||||
<a href={`${window.location.href}?demo=1`}>try the demo</a>
|
||||
.
|
||||
</span>
|
||||
</p>
|
||||
);
|
||||
|
@ -215,8 +224,8 @@ export default class OnboardingModal extends Component {
|
|||
title="Welcome to Cabana"
|
||||
subtitle="Get started by selecting a drive from Explorer or enabling live mode"
|
||||
footer={this.renderModalFooter()}
|
||||
disableClose={true}
|
||||
variations={["wide", "dark"]}
|
||||
disableClose
|
||||
variations={['wide', 'dark']}
|
||||
>
|
||||
{this.renderModalContent()}
|
||||
</Modal>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import cx from "classnames";
|
||||
import Measure from "react-measure";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import Measure from 'react-measure';
|
||||
|
||||
export default class Modal extends Component {
|
||||
static propTypes = {
|
||||
|
@ -36,8 +36,8 @@ export default class Modal extends Component {
|
|||
if (this.props.variations) {
|
||||
const { variations } = this.props;
|
||||
const classes = variations.reduce(
|
||||
(classes, variation) => classes + `cabana-modal--${variation} `,
|
||||
""
|
||||
(classes, variation) => `${classes}cabana-modal--${variation} `,
|
||||
''
|
||||
);
|
||||
return classes;
|
||||
}
|
||||
|
@ -54,14 +54,14 @@ export default class Modal extends Component {
|
|||
render() {
|
||||
return (
|
||||
<div
|
||||
className={cx("cabana-modal", this.readVariationClasses(), {
|
||||
"cabana-modal--not-closable": this.checkClosability(),
|
||||
"cabana-modal--scrollable-y": this.checkYScrollability()
|
||||
className={cx('cabana-modal', this.readVariationClasses(), {
|
||||
'cabana-modal--not-closable': this.checkClosability(),
|
||||
'cabana-modal--scrollable-y': this.checkYScrollability()
|
||||
})}
|
||||
>
|
||||
<Measure
|
||||
bounds
|
||||
onResize={contentRect => {
|
||||
onResize={(contentRect) => {
|
||||
this.updateHeights(contentRect);
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { PART_SEGMENT_LENGTH } from "../config";
|
||||
import { PART_SEGMENT_LENGTH } from '../config';
|
||||
|
||||
export default class PartSelector extends Component {
|
||||
static selectorWidth = 150;
|
||||
|
||||
static propTypes = {
|
||||
onPartChange: PropTypes.func.isRequired,
|
||||
partsCount: PropTypes.number.isRequired,
|
||||
|
@ -29,14 +30,14 @@ export default class PartSelector extends Component {
|
|||
|
||||
makePartStyle(partsCount, selectedPart) {
|
||||
return {
|
||||
left: selectedPart / partsCount * PartSelector.selectorWidth,
|
||||
width: PART_SEGMENT_LENGTH / partsCount * PartSelector.selectorWidth
|
||||
left: (selectedPart / partsCount) * PartSelector.selectorWidth,
|
||||
width: (PART_SEGMENT_LENGTH / partsCount) * PartSelector.selectorWidth
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps, nextState) {
|
||||
if (nextProps.selectedPart !== this.props.selectedPart) {
|
||||
console.log("updating styles for part picker");
|
||||
console.log('updating styles for part picker');
|
||||
const selectedPartStyle = this.makePartStyle(
|
||||
nextProps.partsCount,
|
||||
nextProps.selectedPart
|
||||
|
@ -80,12 +81,12 @@ export default class PartSelector extends Component {
|
|||
partAtClientX(clientX) {
|
||||
const rect = this.selectorRect.getBoundingClientRect();
|
||||
const x = clientX - rect.left;
|
||||
return Math.floor(x * this.props.partsCount / PartSelector.selectorWidth);
|
||||
return Math.floor((x * this.props.partsCount) / PartSelector.selectorWidth);
|
||||
}
|
||||
|
||||
onSelectedPartDragStart(e) {
|
||||
this.setState({ isDragging: true });
|
||||
document.addEventListener("mouseup", this.onSelectedPartDragEnd);
|
||||
document.addEventListener('mouseup', this.onSelectedPartDragEnd);
|
||||
}
|
||||
|
||||
onSelectedPartMouseMove(e) {
|
||||
|
@ -97,7 +98,7 @@ export default class PartSelector extends Component {
|
|||
|
||||
onSelectedPartDragEnd(e) {
|
||||
this.setState({ isDragging: false });
|
||||
document.removeEventListener("mouseup", this.onSelectedPartDragEnd);
|
||||
document.removeEventListener('mouseup', this.onSelectedPartDragEnd);
|
||||
}
|
||||
|
||||
onClick(e) {
|
||||
|
@ -116,7 +117,7 @@ export default class PartSelector extends Component {
|
|||
<div className="cabana-explorer-part-selector">
|
||||
<div
|
||||
className="cabana-explorer-part-selector-track"
|
||||
ref={selector => (this.selectorRect = selector)}
|
||||
ref={(selector) => (this.selectorRect = selector)}
|
||||
style={{ width: PartSelector.selectorWidth }}
|
||||
onMouseMove={this.onSelectedPartMouseMove}
|
||||
onClick={this.onClick}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class PlayButton extends Component {
|
||||
static propTypes = {
|
||||
|
@ -21,29 +21,18 @@ export default class PlayButton extends Component {
|
|||
const { isPlaying } = this.props;
|
||||
if (isPlaying) {
|
||||
if (hover) {
|
||||
return (
|
||||
process.env.PUBLIC_URL + "/img/ic_pause_circle_filled_white_24px.svg"
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
process.env.PUBLIC_URL + "/img/ic_pause_circle_outline_white_24px.svg"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (hover) {
|
||||
return (
|
||||
process.env.PUBLIC_URL + "/img/ic_play_circle_filled_white_24px.svg"
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
process.env.PUBLIC_URL + "/img/ic_play_circle_outline_white_24px.svg"
|
||||
);
|
||||
return `${process.env.PUBLIC_URL}/img/ic_pause_circle_filled_white_24px.svg`;
|
||||
}
|
||||
return `${process.env.PUBLIC_URL}/img/ic_pause_circle_outline_white_24px.svg`;
|
||||
}
|
||||
if (hover) {
|
||||
return `${process.env.PUBLIC_URL}/img/ic_play_circle_filled_white_24px.svg`;
|
||||
}
|
||||
return `${process.env.PUBLIC_URL}/img/ic_play_circle_outline_white_24px.svg`;
|
||||
}
|
||||
|
||||
onClick(e) {
|
||||
let { isPlaying } = this.props;
|
||||
const { isPlaying } = this.props;
|
||||
|
||||
if (!isPlaying) {
|
||||
this.props.onPlay();
|
||||
|
@ -56,7 +45,7 @@ export default class PlayButton extends Component {
|
|||
return (
|
||||
<img
|
||||
src={this.imageSource()}
|
||||
alt={this.props.isPlaying ? "Pause" : "Play"}
|
||||
alt={this.props.isPlaying ? 'Pause' : 'Play'}
|
||||
className={this.props.className}
|
||||
onClick={this.onClick}
|
||||
onMouseOver={() => this.setState({ hover: true })}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Component } from "react";
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class PlaySpeedSelector extends Component {
|
||||
constructor(props) {
|
||||
|
@ -16,8 +16,8 @@ export default class PlaySpeedSelector extends Component {
|
|||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "inline-block",
|
||||
float: "right",
|
||||
display: 'inline-block',
|
||||
float: 'right',
|
||||
margin: 10
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import PlayButton from "../PlayButton";
|
||||
import debounce from "../../utils/debounce";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import PlayButton from '../PlayButton';
|
||||
import debounce from '../../utils/debounce';
|
||||
|
||||
export default class RouteSeeker extends Component {
|
||||
static propTypes = {
|
||||
|
@ -18,10 +18,14 @@ export default class RouteSeeker extends Component {
|
|||
nearestFrameTime: PropTypes.number
|
||||
};
|
||||
|
||||
static hiddenMarkerStyle = { display: "none", left: 0 };
|
||||
static hiddenMarkerStyle = { display: 'none', left: 0 };
|
||||
|
||||
static zeroSeekedBarStyle = { width: 0 };
|
||||
static hiddenTooltipStyle = { display: "none", left: 0 };
|
||||
|
||||
static hiddenTooltipStyle = { display: 'none', left: 0 };
|
||||
|
||||
static markerWidth = 20;
|
||||
|
||||
static tooltipWidth = 50;
|
||||
|
||||
constructor(props) {
|
||||
|
@ -31,7 +35,7 @@ export default class RouteSeeker extends Component {
|
|||
markerStyle: RouteSeeker.hiddenMarkerStyle,
|
||||
tooltipStyle: RouteSeeker.hiddenTooltipStyle,
|
||||
ratio: 0,
|
||||
tooltipTime: "0:00",
|
||||
tooltipTime: '0:00',
|
||||
isPlaying: false,
|
||||
isDragging: false
|
||||
};
|
||||
|
@ -50,8 +54,8 @@ export default class RouteSeeker extends Component {
|
|||
const { ratio } = this.state;
|
||||
|
||||
if (
|
||||
JSON.stringify(this.props.segmentIndices) !==
|
||||
JSON.stringify(nextProps.segmentIndices)
|
||||
JSON.stringify(this.props.segmentIndices)
|
||||
!== JSON.stringify(nextProps.segmentIndices)
|
||||
) {
|
||||
this.setState({
|
||||
seekedBarStyle: RouteSeeker.zeroSeekedBarStyle,
|
||||
|
@ -88,7 +92,7 @@ export default class RouteSeeker extends Component {
|
|||
return 100 * (x / this.progressBar.offsetWidth);
|
||||
}
|
||||
|
||||
updateDraggingSeek = debounce(ratio => this.props.onUserSeek(ratio), 250);
|
||||
updateDraggingSeek = debounce((ratio) => this.props.onUserSeek(ratio), 250);
|
||||
|
||||
onMouseMove(e) {
|
||||
const markerOffsetPct = this.mouseEventXOffsetPercent(e);
|
||||
|
@ -96,18 +100,18 @@ export default class RouteSeeker extends Component {
|
|||
this.onMouseLeave();
|
||||
return;
|
||||
}
|
||||
const markerWidth = RouteSeeker.markerWidth;
|
||||
const { markerWidth } = RouteSeeker;
|
||||
|
||||
const markerLeft = `calc(${markerOffsetPct + "%"} - ${markerWidth / 2}px)`;
|
||||
const markerLeft = `calc(${`${markerOffsetPct}%`} - ${markerWidth / 2}px)`;
|
||||
const markerStyle = {
|
||||
display: "",
|
||||
display: '',
|
||||
left: markerLeft
|
||||
};
|
||||
const tooltipWidth = RouteSeeker.tooltipWidth;
|
||||
const tooltipLeft = `calc(${markerOffsetPct + "%"} - ${tooltipWidth /
|
||||
2}px)`;
|
||||
const { tooltipWidth } = RouteSeeker;
|
||||
const tooltipLeft = `calc(${`${markerOffsetPct}%`} - ${tooltipWidth
|
||||
/ 2}px)`;
|
||||
|
||||
const tooltipStyle = { display: "flex", left: tooltipLeft };
|
||||
const tooltipStyle = { display: 'flex', left: tooltipLeft };
|
||||
const ratio = Math.max(0, markerOffsetPct / 100);
|
||||
if (this.state.isDragging) {
|
||||
this.updateSeekedBar(ratio);
|
||||
|
@ -130,7 +134,7 @@ export default class RouteSeeker extends Component {
|
|||
}
|
||||
|
||||
updateSeekedBar(ratio) {
|
||||
const seekedBarStyle = { width: 100 * ratio + "%" };
|
||||
const seekedBarStyle = { width: `${100 * ratio}%` };
|
||||
this.setState({ seekedBarStyle, ratio });
|
||||
}
|
||||
|
||||
|
@ -210,32 +214,32 @@ export default class RouteSeeker extends Component {
|
|||
return (
|
||||
<div className="cabana-explorer-visuals-camera-seeker">
|
||||
<PlayButton
|
||||
className={"cabana-explorer-visuals-camera-seeker-playbutton"}
|
||||
className="cabana-explorer-visuals-camera-seeker-playbutton"
|
||||
onPlay={this.onPlay}
|
||||
onPause={this.onPause}
|
||||
isPlaying={this.state.isPlaying}
|
||||
/>
|
||||
<div
|
||||
className={"cabana-explorer-visuals-camera-seeker-progress"}
|
||||
className="cabana-explorer-visuals-camera-seeker-progress"
|
||||
onMouseMove={this.onMouseMove}
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
onMouseDown={this.onMouseDown}
|
||||
onMouseUp={this.onMouseUp}
|
||||
onClick={this.onClick}
|
||||
ref={ref => (this.progressBar = ref)}
|
||||
ref={(ref) => (this.progressBar = ref)}
|
||||
>
|
||||
<div
|
||||
className={"cabana-explorer-visuals-camera-seeker-progress-tooltip"}
|
||||
className="cabana-explorer-visuals-camera-seeker-progress-tooltip"
|
||||
style={tooltipStyle}
|
||||
>
|
||||
{this.state.tooltipTime}
|
||||
</div>
|
||||
<div
|
||||
className={"cabana-explorer-visuals-camera-seeker-progress-marker"}
|
||||
className="cabana-explorer-visuals-camera-seeker-progress-marker"
|
||||
style={markerStyle}
|
||||
/>
|
||||
<div
|
||||
className={"cabana-explorer-visuals-camera-seeker-progress-inner"}
|
||||
className="cabana-explorer-visuals-camera-seeker-progress-inner"
|
||||
style={seekedBarStyle}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
import RouteSeeker from "./RouteSeeker";
|
||||
import RouteSeeker from './RouteSeeker';
|
||||
|
||||
export default RouteSeeker;
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { StyleSheet, css } from "aphrodite/no-important";
|
||||
import { derived as RouteApi, video as VideoApi } from "@commaai/comma-api";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, css } from 'aphrodite/no-important';
|
||||
import { derived as RouteApi, video as VideoApi } from '@commaai/comma-api';
|
||||
|
||||
import HLS from "./HLS";
|
||||
import RouteSeeker from "./RouteSeeker/RouteSeeker";
|
||||
import HLS from './HLS';
|
||||
import RouteSeeker from './RouteSeeker/RouteSeeker';
|
||||
|
||||
const Styles = StyleSheet.create({
|
||||
loadingOverlay: {
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
zIndex: 3
|
||||
},
|
||||
loadingSpinner: {
|
||||
width: "25%",
|
||||
height: "25%",
|
||||
display: "block"
|
||||
width: '25%',
|
||||
height: '25%',
|
||||
display: 'block'
|
||||
},
|
||||
img: {
|
||||
height: 480,
|
||||
display: "block",
|
||||
position: "absolute",
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
zIndex: 2
|
||||
},
|
||||
hls: {
|
||||
zIndex: 1,
|
||||
height: 480,
|
||||
backgroundColor: "rgba(0,0,0,0.9)"
|
||||
backgroundColor: 'rgba(0,0,0,0.9)'
|
||||
},
|
||||
seekBar: {
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
zIndex: 4
|
||||
}
|
||||
});
|
||||
|
@ -79,17 +79,17 @@ export default class RouteVideoSync extends Component {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
this.props.userSeekIndex !== nextProps.userSeekIndex ||
|
||||
this.props.canFrameOffset !== nextProps.canFrameOffset ||
|
||||
(this.props.message &&
|
||||
nextProps.message &&
|
||||
this.props.message.entries.length !== nextProps.message.entries.length)
|
||||
this.props.userSeekIndex !== nextProps.userSeekIndex
|
||||
|| this.props.canFrameOffset !== nextProps.canFrameOffset
|
||||
|| (this.props.message
|
||||
&& nextProps.message
|
||||
&& this.props.message.entries.length !== nextProps.message.entries.length)
|
||||
) {
|
||||
this.setState({ shouldRestartHls: true });
|
||||
}
|
||||
if (
|
||||
nextProps.userSeekTime &&
|
||||
this.props.userSeekTime !== nextProps.userSeekTime
|
||||
nextProps.userSeekTime
|
||||
&& this.props.userSeekTime !== nextProps.userSeekTime
|
||||
) {
|
||||
if (this.state.videoElement) {
|
||||
this.state.videoElement.currentTime = nextProps.userSeekTime;
|
||||
|
@ -111,8 +111,8 @@ export default class RouteVideoSync extends Component {
|
|||
<div className={css(Styles.loadingOverlay)}>
|
||||
<img
|
||||
className={css(Styles.loadingSpinner)}
|
||||
src={process.env.PUBLIC_URL + "/img/loading.svg"}
|
||||
alt={"Loading video"}
|
||||
src={`${process.env.PUBLIC_URL}/img/loading.svg`}
|
||||
alt="Loading video"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -154,7 +154,7 @@ export default class RouteVideoSync extends Component {
|
|||
|
||||
segmentProgress(currentTime) {
|
||||
// returns progress as number in [0,1]
|
||||
let startTime = this.startTime();
|
||||
const startTime = this.startTime();
|
||||
|
||||
if (currentTime < startTime) {
|
||||
currentTime = startTime;
|
||||
|
@ -175,12 +175,12 @@ export default class RouteVideoSync extends Component {
|
|||
onUserSeek(ratio) {
|
||||
/* ratio in [0,1] */
|
||||
|
||||
let { videoElement } = this.state;
|
||||
const { videoElement } = this.state;
|
||||
if (isNaN(videoElement.duration)) {
|
||||
this.setState({ shouldRestartHls: true }, funcSeekToRatio);
|
||||
return;
|
||||
}
|
||||
let seekTime = this.ratioTime(ratio);
|
||||
const seekTime = this.ratioTime(ratio);
|
||||
videoElement.currentTime = seekTime;
|
||||
|
||||
const funcSeekToRatio = () => this.props.onUserSeek(seekTime);
|
||||
|
@ -203,7 +203,7 @@ export default class RouteVideoSync extends Component {
|
|||
<img
|
||||
src={this.nearestFrameUrl()}
|
||||
className={css(Styles.img)}
|
||||
alt={"Camera preview at t = " + Math.round(this.props.userSeekTime)}
|
||||
alt={`Camera preview at t = ${Math.round(this.props.userSeekTime)}`}
|
||||
/>
|
||||
) : null}
|
||||
<HLS
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
import cx from "classnames";
|
||||
import PropTypes from "prop-types";
|
||||
import FileSaver from "file-saver";
|
||||
import React, { Component } from 'react';
|
||||
import cx from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import FileSaver from 'file-saver';
|
||||
|
||||
import OpenDbc from "../api/OpenDbc";
|
||||
import DBC from "../models/can/dbc";
|
||||
import Modal from "./Modals/baseModal";
|
||||
import OpenDbc from '../api/OpenDbc';
|
||||
import DBC from '../models/can/dbc';
|
||||
import Modal from './Modals/baseModal';
|
||||
// import TabStyles from '../styles/modal-tabs';
|
||||
|
||||
export default class SaveDbcModal extends Component {
|
||||
|
@ -22,11 +22,11 @@ export default class SaveDbcModal extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
tab: "GitHub",
|
||||
tab: 'GitHub',
|
||||
openDbcFork: null,
|
||||
dbcFilename: this.props.sourceDbcFilename,
|
||||
tabs: ["GitHub", "Download"],
|
||||
commitMessage: "OpenDBC updates"
|
||||
tabs: ['GitHub', 'Download'],
|
||||
commitMessage: 'OpenDBC updates'
|
||||
};
|
||||
|
||||
this.commitToGitHub = this.commitToGitHub.bind(this);
|
||||
|
@ -44,7 +44,7 @@ export default class SaveDbcModal extends Component {
|
|||
|
||||
async commitToGitHub() {
|
||||
const { openDbcFork, dbcFilename } = this.state;
|
||||
const filename = dbcFilename.replace(/\.dbc/g, "") + ".dbc";
|
||||
const filename = `${dbcFilename.replace(/\.dbc/g, '')}.dbc`;
|
||||
const success = await this.props.openDbcClient.commitFile(
|
||||
openDbcFork,
|
||||
filename,
|
||||
|
@ -58,9 +58,9 @@ export default class SaveDbcModal extends Component {
|
|||
|
||||
async downloadDbcFile() {
|
||||
const blob = new Blob([this.props.dbc.text()], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
type: 'text/plain;charset=utf-8'
|
||||
});
|
||||
const filename = this.state.dbcFilename.replace(/\.dbc/g, "") + ".dbc";
|
||||
const filename = `${this.state.dbcFilename.replace(/\.dbc/g, '')}.dbc`;
|
||||
FileSaver.saveAs(blob, filename, true);
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ export default class SaveDbcModal extends Component {
|
|||
|
||||
const interval = window.setInterval(() => {
|
||||
if (!isTimedOut) {
|
||||
this.props.openDbcClient.getUserOpenDbcFork().then(openDbcFork => {
|
||||
this.props.openDbcClient.getUserOpenDbcFork().then((openDbcFork) => {
|
||||
if (openDbcFork !== null) {
|
||||
this.setState({ openDbcFork });
|
||||
window.clearInterval(interval);
|
||||
|
@ -92,11 +92,12 @@ export default class SaveDbcModal extends Component {
|
|||
|
||||
primaryActionDisabled() {
|
||||
const { tab } = this.state;
|
||||
if (tab === "GitHub") {
|
||||
if (tab === 'GitHub') {
|
||||
return (
|
||||
this.state.openDbcFork != null && this.state.dbcFilename.length > 0
|
||||
);
|
||||
} else if (tab === "Download") {
|
||||
}
|
||||
if (tab === 'Download') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +118,11 @@ export default class SaveDbcModal extends Component {
|
|||
content = (
|
||||
<button disabled>
|
||||
<i className="fa fa-code-fork" />
|
||||
<span> Forked: {openDbcFork}</span>
|
||||
<span>
|
||||
{' '}
|
||||
Forked:
|
||||
{openDbcFork}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
} else if (this.props.hasGithubAuth) {
|
||||
|
@ -144,9 +149,9 @@ export default class SaveDbcModal extends Component {
|
|||
<input
|
||||
type="text"
|
||||
id="filename"
|
||||
value={this.state.dbcFilename.replace(/\.dbc/g, "")}
|
||||
value={this.state.dbcFilename.replace(/\.dbc/g, '')}
|
||||
size={this.state.dbcFilename.length + 2}
|
||||
onChange={e => this.setState({ dbcFilename: e.target.value })}
|
||||
onChange={(e) => this.setState({ dbcFilename: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -155,19 +160,17 @@ export default class SaveDbcModal extends Component {
|
|||
renderTabNavigation() {
|
||||
return (
|
||||
<div className="cabana-tabs-navigation">
|
||||
{this.state.tabs.map(tab => {
|
||||
return (
|
||||
<a
|
||||
className={cx({ "is-active": this.state.tab === tab })}
|
||||
onClick={() => {
|
||||
this.setState({ tab });
|
||||
}}
|
||||
key={tab}
|
||||
>
|
||||
<span>{tab}</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
{this.state.tabs.map((tab) => (
|
||||
<a
|
||||
className={cx({ 'is-active': this.state.tab === tab })}
|
||||
onClick={() => {
|
||||
this.setState({ tab });
|
||||
}}
|
||||
key={tab}
|
||||
>
|
||||
<span>{tab}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -183,7 +186,7 @@ export default class SaveDbcModal extends Component {
|
|||
type="text"
|
||||
id="commit-message"
|
||||
value={this.state.commitMessage}
|
||||
onChange={e => this.setState({ commitMessage: e.target.value })}
|
||||
onChange={(e) => this.setState({ commitMessage: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -191,7 +194,7 @@ export default class SaveDbcModal extends Component {
|
|||
|
||||
renderTabContent() {
|
||||
const { tab } = this.state;
|
||||
if (tab === "GitHub") {
|
||||
if (tab === 'GitHub') {
|
||||
return (
|
||||
<div>
|
||||
{this.renderForkStep()}
|
||||
|
@ -199,14 +202,15 @@ export default class SaveDbcModal extends Component {
|
|||
{this.renderCommitMessage()}
|
||||
</div>
|
||||
);
|
||||
} else if (tab === "Download") {
|
||||
}
|
||||
if (tab === 'Download') {
|
||||
return <div>{this.renderFilenameField()}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
renderActions() {
|
||||
const { tab } = this.state;
|
||||
if (tab === "GitHub") {
|
||||
if (tab === 'GitHub') {
|
||||
return (
|
||||
<div>
|
||||
<button className="button--inverted" onClick={this.props.handleClose}>
|
||||
|
@ -217,7 +221,8 @@ export default class SaveDbcModal extends Component {
|
|||
</button>
|
||||
</div>
|
||||
);
|
||||
} else if (tab === "Download") {
|
||||
}
|
||||
if (tab === 'Download') {
|
||||
return (
|
||||
<div>
|
||||
<button className="button--inverted" onClick={this.props.handleClose}>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// SignalLegend.js
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import SignalLegendEntry from "./SignalLegendEntry";
|
||||
import SignalLegendEntry from './SignalLegendEntry';
|
||||
|
||||
export default class SignalLegend extends Component {
|
||||
static propTypes = {
|
||||
|
@ -23,13 +23,13 @@ export default class SignalLegend extends Component {
|
|||
expandedSignals: []
|
||||
};
|
||||
|
||||
toggleExpandSignal = s => {
|
||||
toggleExpandSignal = (s) => {
|
||||
const { expandedSignals } = this.state;
|
||||
if (!expandedSignals.includes(s.uid)) {
|
||||
const updatedExpandedSignals = [...expandedSignals, s.uid];
|
||||
this.setState({ expandedSignals: updatedExpandedSignals });
|
||||
} else {
|
||||
const updatedExpandedSignals = expandedSignals.filter(i => i !== s.uid);
|
||||
const updatedExpandedSignals = expandedSignals.filter((i) => i !== s.uid);
|
||||
this.setState({ expandedSignals: updatedExpandedSignals });
|
||||
}
|
||||
};
|
||||
|
@ -44,9 +44,8 @@ export default class SignalLegend extends Component {
|
|||
.sort(([_, signal1], [__, signal2]) => {
|
||||
if (signal1.startBit < signal2.startBit) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
})
|
||||
.map(([signalName, signal]) => {
|
||||
const { colors } = signals[signalName];
|
||||
|
@ -73,10 +72,8 @@ export default class SignalLegend extends Component {
|
|||
});
|
||||
|
||||
const signalRows = signalRowsNested
|
||||
.filter(row => row != null)
|
||||
.reduce((a, b) => {
|
||||
return a.concat(b);
|
||||
}, []);
|
||||
.filter((row) => row != null)
|
||||
.reduce((a, b) => a.concat(b), []);
|
||||
|
||||
return <div className="cabana-explorer-signals-legend">{signalRows}</div>;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import styled from "react-emotion";
|
||||
import styled from 'react-emotion';
|
||||
|
||||
// color bar on the left side of the signals legend
|
||||
export default styled("div")`
|
||||
export default styled('div')`
|
||||
display: block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 1.5%;
|
||||
opacity: ${({ isHighlighted }) => (isHighlighted ? 0.5 : 0.3)};
|
||||
background-color: rgb(${({ rgb }) => rgb.join(",")});
|
||||
background-color: rgb(${({ rgb }) => rgb.join(',')});
|
||||
`;
|
||||
|
|
|
@ -1,44 +1,41 @@
|
|||
import DbcUtils from "../../utils/dbc";
|
||||
import DbcUtils from '../../utils/dbc';
|
||||
|
||||
const unsignedTransformation = field => {
|
||||
return (value, signal) => {
|
||||
if (value !== "") {
|
||||
value = Number(value) || 0;
|
||||
const unsignedTransformation = (field) => (value, signal) => {
|
||||
if (value !== '') {
|
||||
value = Number(value) || 0;
|
||||
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
}
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
}
|
||||
signal[field] = value;
|
||||
return signal;
|
||||
};
|
||||
}
|
||||
signal[field] = value;
|
||||
return signal;
|
||||
};
|
||||
|
||||
export default [
|
||||
{
|
||||
field: "name",
|
||||
title: "Name",
|
||||
type: "string"
|
||||
field: 'name',
|
||||
title: 'Name',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
field: "size",
|
||||
title: "Size",
|
||||
type: "number",
|
||||
transform: unsignedTransformation("size")
|
||||
field: 'size',
|
||||
title: 'Size',
|
||||
type: 'number',
|
||||
transform: unsignedTransformation('size')
|
||||
},
|
||||
{
|
||||
field: "startBit",
|
||||
title: signal =>
|
||||
signal.isLittleEndian ? "Least significant bit" : "Most significant bit",
|
||||
type: "number",
|
||||
transform: unsignedTransformation("startBit")
|
||||
field: 'startBit',
|
||||
title: (signal) => (signal.isLittleEndian ? 'Least significant bit' : 'Most significant bit'),
|
||||
type: 'number',
|
||||
transform: unsignedTransformation('startBit')
|
||||
},
|
||||
{
|
||||
field: "isLittleEndian",
|
||||
title: "Endianness",
|
||||
type: "option",
|
||||
field: 'isLittleEndian',
|
||||
title: 'Endianness',
|
||||
type: 'option',
|
||||
options: {
|
||||
options: ["Little", "Big"],
|
||||
options: ['Little', 'Big'],
|
||||
optionValues: { Little: true, Big: false }
|
||||
},
|
||||
transform: (isLittleEndian, signal) => {
|
||||
|
@ -47,8 +44,8 @@ export default [
|
|||
|
||||
if (isLittleEndian) {
|
||||
// big endian -> little endian
|
||||
const startByte = Math.floor(signal.startBit / 8),
|
||||
endByte = Math.floor((signal.startBit - signal.size + 1) / 8);
|
||||
const startByte = Math.floor(signal.startBit / 8);
|
||||
const endByte = Math.floor((signal.startBit - signal.size + 1) / 8);
|
||||
|
||||
if (startByte === endByte) {
|
||||
signal.startBit = signal.startBit - signal.size + 1;
|
||||
|
@ -57,8 +54,8 @@ export default [
|
|||
}
|
||||
} else {
|
||||
// little endian -> big endian
|
||||
const startByte = Math.floor(signal.startBit / 8),
|
||||
endByte = Math.floor((signal.startBit + signal.size - 1) / 8);
|
||||
const startByte = Math.floor(signal.startBit / 8);
|
||||
const endByte = Math.floor((signal.startBit + signal.size - 1) / 8);
|
||||
|
||||
if (startByte === endByte) {
|
||||
signal.startBit = signal.startBit + signal.size - 1;
|
||||
|
@ -72,42 +69,42 @@ export default [
|
|||
}
|
||||
},
|
||||
{
|
||||
field: "isSigned",
|
||||
title: "Sign",
|
||||
type: "option",
|
||||
field: 'isSigned',
|
||||
title: 'Sign',
|
||||
type: 'option',
|
||||
options: {
|
||||
options: ["Signed", "Unsigned"],
|
||||
options: ['Signed', 'Unsigned'],
|
||||
optionValues: { Signed: true, Unsigned: false }
|
||||
}
|
||||
},
|
||||
{
|
||||
field: "factor",
|
||||
title: "Factor",
|
||||
type: "number"
|
||||
field: 'factor',
|
||||
title: 'Factor',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
field: "offset",
|
||||
title: "Offset",
|
||||
type: "number"
|
||||
field: 'offset',
|
||||
title: 'Offset',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
field: "unit",
|
||||
title: "Unit",
|
||||
type: "string"
|
||||
field: 'unit',
|
||||
title: 'Unit',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
field: "comment",
|
||||
title: "Comment",
|
||||
type: "string"
|
||||
field: 'comment',
|
||||
title: 'Comment',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
field: "min",
|
||||
title: "Minimum value",
|
||||
type: "number"
|
||||
field: 'min',
|
||||
title: 'Minimum value',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
field: "max",
|
||||
title: "Maximum value",
|
||||
type: "number"
|
||||
field: 'max',
|
||||
title: 'Maximum value',
|
||||
type: 'number'
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Component } from "react";
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class Field extends Component {
|
||||
render() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import Field from "./Field";
|
||||
import React from 'react';
|
||||
import Field from './Field';
|
||||
|
||||
export default ({
|
||||
fieldSpec,
|
||||
|
@ -14,27 +14,27 @@ export default ({
|
|||
|
||||
if (isExpanded) {
|
||||
let value = signalEdited;
|
||||
if (value !== "") {
|
||||
let num = Number(value);
|
||||
value = isNaN(num) ? "" : num;
|
||||
if (value !== '') {
|
||||
const num = Number(value);
|
||||
value = isNaN(num) ? '' : num;
|
||||
}
|
||||
valueCol = (
|
||||
<input
|
||||
id={htmlFor}
|
||||
type="number"
|
||||
value={value}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
updateField(fieldSpec, e.target.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
let value = signal[field];
|
||||
const value = signal[field];
|
||||
valueCol = <span>{value}</span>;
|
||||
}
|
||||
return (
|
||||
<Field
|
||||
title={typeof title === "function" ? title(signal) : title}
|
||||
title={typeof title === 'function' ? title(signal) : title}
|
||||
htmlFor={htmlFor}
|
||||
>
|
||||
{valueCol}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import Field from "./Field";
|
||||
import React from 'react';
|
||||
import Field from './Field';
|
||||
|
||||
import { swapKeysAndValues } from "../../utils/object";
|
||||
import { swapKeysAndValues } from '../../utils/object';
|
||||
|
||||
export default ({
|
||||
fieldSpec,
|
||||
|
@ -14,10 +14,10 @@ export default ({
|
|||
const { field, title } = fieldSpec;
|
||||
const htmlFor = `${signal.name}_${field}`;
|
||||
const { options, optionValues } = fieldSpec.options;
|
||||
let valueOptions = swapKeysAndValues(optionValues);
|
||||
const valueOptions = swapKeysAndValues(optionValues);
|
||||
|
||||
if (isExpanded) {
|
||||
const optionEles = options.map(opt => (
|
||||
const optionEles = options.map((opt) => (
|
||||
<option key={opt} value={optionValues[opt]}>
|
||||
{opt}
|
||||
</option>
|
||||
|
@ -26,8 +26,8 @@ export default ({
|
|||
<select
|
||||
id={htmlFor}
|
||||
defaultValue={signalEdited}
|
||||
onChange={e => {
|
||||
updateField(fieldSpec, e.target.value === "true");
|
||||
onChange={(e) => {
|
||||
updateField(fieldSpec, e.target.value === 'true');
|
||||
}}
|
||||
>
|
||||
{optionEles}
|
||||
|
@ -39,7 +39,7 @@ export default ({
|
|||
|
||||
return (
|
||||
<Field
|
||||
title={typeof title === "function" ? title(signal) : title}
|
||||
title={typeof title === 'function' ? title(signal) : title}
|
||||
htmlFor={htmlFor}
|
||||
>
|
||||
{valueCol}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
import FIELDS from "./FIELDS";
|
||||
import NumberField from "./NumberField";
|
||||
import StringField from "./StringField";
|
||||
import OptionField from "./OptionField";
|
||||
import FIELDS from './FIELDS';
|
||||
import NumberField from './NumberField';
|
||||
import StringField from './StringField';
|
||||
import OptionField from './OptionField';
|
||||
|
||||
const FieldMap = {
|
||||
number: NumberField,
|
||||
|
@ -17,31 +17,29 @@ export default ({
|
|||
isExpanded,
|
||||
getSignalEdited,
|
||||
update
|
||||
}) => {
|
||||
return (
|
||||
<div className="signals-legend-entry-form">
|
||||
{FIELDS.map(field => {
|
||||
const Node = FieldMap[field.type];
|
||||
return (
|
||||
<div className="signals-legend-entry-form-field" key={field.field}>
|
||||
<Node
|
||||
fieldSpec={field}
|
||||
signal={signal}
|
||||
isExpanded={isExpanded}
|
||||
signalEdited={getSignalEdited(field.field)}
|
||||
updateField={update}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="signals-legend-entry-form-remove">
|
||||
<button
|
||||
className="button--tiny button--alpha"
|
||||
onClick={() => onSignalRemove(signal)}
|
||||
>
|
||||
Remove Signal
|
||||
</button>
|
||||
</div>
|
||||
}) => (
|
||||
<div className="signals-legend-entry-form">
|
||||
{FIELDS.map((field) => {
|
||||
const Node = FieldMap[field.type];
|
||||
return (
|
||||
<div className="signals-legend-entry-form-field" key={field.field}>
|
||||
<Node
|
||||
fieldSpec={field}
|
||||
signal={signal}
|
||||
isExpanded={isExpanded}
|
||||
signalEdited={getSignalEdited(field.field)}
|
||||
updateField={update}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="signals-legend-entry-form-remove">
|
||||
<button
|
||||
className="button--tiny button--alpha"
|
||||
onClick={() => onSignalRemove(signal)}
|
||||
>
|
||||
Remove Signal
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import Field from "./Field";
|
||||
import React from 'react';
|
||||
import Field from './Field';
|
||||
|
||||
export default ({
|
||||
fieldSpec,
|
||||
|
@ -16,8 +16,8 @@ export default ({
|
|||
<input
|
||||
id={htmlFor}
|
||||
type="text"
|
||||
value={signalEdited || ""}
|
||||
onChange={e => {
|
||||
value={signalEdited || ''}
|
||||
onChange={(e) => {
|
||||
updateField(fieldSpec, e.target.value);
|
||||
}}
|
||||
/>
|
||||
|
@ -28,7 +28,7 @@ export default ({
|
|||
|
||||
return (
|
||||
<Field
|
||||
title={typeof title === "function" ? title(signal) : title}
|
||||
title={typeof title === 'function' ? title(signal) : title}
|
||||
htmlFor={htmlFor}
|
||||
>
|
||||
{valueCol}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// SignalLegendEntry.js
|
||||
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import cx from "classnames";
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
|
||||
import Signal from "../../models/can/signal";
|
||||
import SignalForm from "./SignalForm";
|
||||
import ColorBar from "./ColorBar";
|
||||
import FIELDS from "./FIELDS";
|
||||
import Signal from '../../models/can/signal';
|
||||
import SignalForm from './SignalForm';
|
||||
import ColorBar from './ColorBar';
|
||||
import FIELDS from './FIELDS';
|
||||
|
||||
export default class SignalLegendEntry extends Component {
|
||||
static propTypes = {
|
||||
|
@ -25,9 +25,7 @@ export default class SignalLegendEntry extends Component {
|
|||
isExpanded: PropTypes.bool
|
||||
};
|
||||
|
||||
static fieldSpecForName = name => {
|
||||
return FIELDS.find(field => field.field === name);
|
||||
};
|
||||
static fieldSpecForName = (name) => FIELDS.find((field) => field.field === name);
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -66,7 +64,7 @@ export default class SignalLegendEntry extends Component {
|
|||
this.props.onSignalChange(signalCopy, signal);
|
||||
};
|
||||
|
||||
toggleEditing = e => {
|
||||
toggleEditing = (e) => {
|
||||
if (this.props.isLogEvent) {
|
||||
return;
|
||||
}
|
||||
|
@ -81,9 +79,9 @@ export default class SignalLegendEntry extends Component {
|
|||
const fieldSpec = SignalLegendEntry.fieldSpecForName(field);
|
||||
|
||||
if (
|
||||
fieldSpec &&
|
||||
fieldSpec.type === "number" &&
|
||||
isNaN(parseInt(value, 10))
|
||||
fieldSpec
|
||||
&& fieldSpec.type === 'number'
|
||||
&& isNaN(parseInt(value, 10))
|
||||
) {
|
||||
value = 0;
|
||||
}
|
||||
|
@ -103,22 +101,23 @@ export default class SignalLegendEntry extends Component {
|
|||
e.stopPropagation();
|
||||
};
|
||||
|
||||
toggleSignalPlot = e => {
|
||||
toggleSignalPlot = (e) => {
|
||||
const { signal, isPlotted } = this.props;
|
||||
e.preventDefault();
|
||||
this.props.onSignalPlotChange(!isPlotted, signal.uid);
|
||||
};
|
||||
|
||||
getSignalEdited = field => {
|
||||
return this.state.signalEdited[field];
|
||||
};
|
||||
getSignalEdited = (field) => this.state.signalEdited[field];
|
||||
|
||||
render() {
|
||||
const { signal, isHighlighted, color, isPlotted, isExpanded } = this.props;
|
||||
const expandedEntryClass = isExpanded ? "is-expanded" : null;
|
||||
const plottedButtonClass = isPlotted ? "button" : "button--alpha";
|
||||
const {
|
||||
signal, isHighlighted, color, isPlotted, isExpanded
|
||||
} = this.props;
|
||||
const expandedEntryClass = isExpanded ? 'is-expanded' : null;
|
||||
const plottedButtonClass = isPlotted ? 'button' : 'button--alpha';
|
||||
return (
|
||||
<div
|
||||
className={cx("signals-legend-entry", expandedEntryClass)}
|
||||
className={cx('signals-legend-entry', expandedEntryClass)}
|
||||
onMouseEnter={() => this.props.onSignalHover(signal)}
|
||||
onMouseLeave={() => this.props.onSignalHoverEnd(signal)}
|
||||
>
|
||||
|
@ -134,8 +133,8 @@ export default class SignalLegendEntry extends Component {
|
|||
className="signals-legend-entry-header-action"
|
||||
onClick={this.toggleSignalPlot}
|
||||
>
|
||||
<button className={cx("button--tiny", plottedButtonClass)}>
|
||||
{isPlotted ? "Hide Plot" : "Show Plot"}
|
||||
<button className={cx('button--tiny', plottedButtonClass)}>
|
||||
{isPlotted ? 'Hide Plot' : 'Show Plot'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import SignalLegendEntry from ".";
|
||||
import Signal from "../../models/can/signal";
|
||||
import React from "react";
|
||||
import { shallow, mount, render } from "enzyme";
|
||||
import { StyleSheetTestUtils } from "aphrodite";
|
||||
import React from 'react';
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
import { StyleSheetTestUtils } from 'aphrodite';
|
||||
import Signal from '../../models/can/signal';
|
||||
import SignalLegendEntry from '.';
|
||||
|
||||
// Prevents style injection from firing after test finishes
|
||||
// and jsdom is torn down.
|
||||
|
@ -14,11 +14,11 @@ afterEach(() => {
|
|||
});
|
||||
|
||||
function createSignalLegendEntry(props) {
|
||||
let signal = props.signal,
|
||||
onSignalChange = props.onSignalChange,
|
||||
onTentativeSignalChange = props.onTentativeSignalChange;
|
||||
let { signal } = props;
|
||||
let { onSignalChange } = props;
|
||||
let { onTentativeSignalChange } = props;
|
||||
if (signal === undefined) {
|
||||
signal = new Signal({ name: "NEW_SIGNAL" });
|
||||
signal = new Signal({ name: 'NEW_SIGNAL' });
|
||||
}
|
||||
if (onSignalChange === undefined) {
|
||||
onSignalChange = () => {};
|
||||
|
@ -37,9 +37,9 @@ function createSignalLegendEntry(props) {
|
|||
);
|
||||
}
|
||||
|
||||
test("a little endian signal spanning one byte should adjust its startBit switching to big endian, preserving its bit coverage", () => {
|
||||
test('a little endian signal spanning one byte should adjust its startBit switching to big endian, preserving its bit coverage', () => {
|
||||
const signal = new Signal({
|
||||
name: "signal",
|
||||
name: 'signal',
|
||||
startBit: 0,
|
||||
size: 8,
|
||||
isLittleEndian: true
|
||||
|
@ -47,30 +47,30 @@ test("a little endian signal spanning one byte should adjust its startBit switch
|
|||
|
||||
const component = createSignalLegendEntry({ signal });
|
||||
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
|
||||
"isLittleEndian"
|
||||
'isLittleEndian'
|
||||
);
|
||||
component.instance().updateField(endiannessFieldSpec, false);
|
||||
|
||||
const signalEdited = component.state("signalEdited");
|
||||
const signalEdited = component.state('signalEdited');
|
||||
expect(signalEdited.isLittleEndian).toBe(false);
|
||||
expect(signalEdited.startBit).toBe(7);
|
||||
expect(signalEdited.size).toBe(8);
|
||||
});
|
||||
|
||||
test("a big endian signal spanning two bytes should should adjust its startBit switching to little endian, preserving its bit coverage", () => {
|
||||
test('a big endian signal spanning two bytes should should adjust its startBit switching to little endian, preserving its bit coverage', () => {
|
||||
const signal = new Signal({
|
||||
name: "signal",
|
||||
name: 'signal',
|
||||
startBit: 7,
|
||||
size: 8,
|
||||
isLittleEndian: false
|
||||
});
|
||||
const component = createSignalLegendEntry({ signal });
|
||||
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
|
||||
"isLittleEndian"
|
||||
'isLittleEndian'
|
||||
);
|
||||
component.instance().updateField(endiannessFieldSpec, true);
|
||||
|
||||
const signalEdited = component.state("signalEdited");
|
||||
const signalEdited = component.state('signalEdited');
|
||||
expect(signalEdited.isLittleEndian).toBe(true);
|
||||
expect(signalEdited.startBit).toBe(0);
|
||||
expect(signalEdited.size).toBe(8);
|
||||
|
@ -78,7 +78,7 @@ test("a big endian signal spanning two bytes should should adjust its startBit s
|
|||
|
||||
test("a big endian signal spanning one and a half bytes should adjust its startBit switching to little endian, preserving the first byte's coverage", () => {
|
||||
const signal = new Signal({
|
||||
name: "signal",
|
||||
name: 'signal',
|
||||
startBit: 7,
|
||||
size: 12,
|
||||
isLittleEndian: false
|
||||
|
@ -86,49 +86,49 @@ test("a big endian signal spanning one and a half bytes should adjust its startB
|
|||
|
||||
const component = createSignalLegendEntry({ signal });
|
||||
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
|
||||
"isLittleEndian"
|
||||
'isLittleEndian'
|
||||
);
|
||||
component.instance().updateField(endiannessFieldSpec, true);
|
||||
|
||||
const signalEdited = component.state("signalEdited");
|
||||
const signalEdited = component.state('signalEdited');
|
||||
expect(signalEdited.isLittleEndian).toBe(true);
|
||||
expect(signalEdited.startBit).toBe(0);
|
||||
expect(signalEdited.size).toBe(12);
|
||||
});
|
||||
|
||||
test("a little endian signal spanning 3 bits on one byte should adjust its startBit switching to big endian, preserving its bit coverage", () => {
|
||||
test('a little endian signal spanning 3 bits on one byte should adjust its startBit switching to big endian, preserving its bit coverage', () => {
|
||||
const signal = new Signal({
|
||||
name: "signal",
|
||||
name: 'signal',
|
||||
startBit: 13,
|
||||
size: 3,
|
||||
isLittleEndian: true
|
||||
});
|
||||
const component = createSignalLegendEntry({ signal });
|
||||
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
|
||||
"isLittleEndian"
|
||||
'isLittleEndian'
|
||||
);
|
||||
component.instance().updateField(endiannessFieldSpec, false);
|
||||
|
||||
const signalEdited = component.state("signalEdited");
|
||||
const signalEdited = component.state('signalEdited');
|
||||
expect(signalEdited.isLittleEndian).toBe(false);
|
||||
expect(signalEdited.startBit).toBe(15);
|
||||
expect(signalEdited.size).toBe(3);
|
||||
});
|
||||
|
||||
test("a big endian signal spanning 3 bytes on one byte should adjust its startBit switching to little endian, preserving its bit coverage", () => {
|
||||
test('a big endian signal spanning 3 bytes on one byte should adjust its startBit switching to little endian, preserving its bit coverage', () => {
|
||||
const signal = new Signal({
|
||||
name: "signal",
|
||||
name: 'signal',
|
||||
startBit: 15,
|
||||
size: 3,
|
||||
isLittleEndian: false
|
||||
});
|
||||
const component = createSignalLegendEntry({ signal });
|
||||
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
|
||||
"isLittleEndian"
|
||||
'isLittleEndian'
|
||||
);
|
||||
component.instance().updateField(endiannessFieldSpec, true);
|
||||
|
||||
const signalEdited = component.state("signalEdited");
|
||||
const signalEdited = component.state('signalEdited');
|
||||
expect(signalEdited.isLittleEndian).toBe(true);
|
||||
expect(signalEdited.startBit).toBe(13);
|
||||
expect(signalEdited.size).toBe(3);
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
import { getUrlParameter } from "./utils/url";
|
||||
import { getUrlParameter } from './utils/url';
|
||||
|
||||
const ENV = process.env.NODE_ENV === "production" ? "prod" : "debug";
|
||||
const ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'debug';
|
||||
|
||||
const ENV_GITHUB_CLIENT_ID = {
|
||||
debug: "f1e42d14f45491f9ca34",
|
||||
prod: "4b43250e7499a97d62a5"
|
||||
debug: 'f1e42d14f45491f9ca34',
|
||||
prod: '4b43250e7499a97d62a5'
|
||||
};
|
||||
export const GITHUB_CLIENT_ID = ENV_GITHUB_CLIENT_ID[ENV];
|
||||
|
||||
const ENV_GITHUB_REDIRECT_URL = {
|
||||
debug: "http://127.0.0.1:1235/callback",
|
||||
prod: "https://api.comma.ai/cabana/ghcallback"
|
||||
debug: 'http://127.0.0.1:1235/callback',
|
||||
prod: 'https://api.comma.ai/cabana/ghcallback'
|
||||
};
|
||||
export const GITHUB_REDIRECT_URL = ENV_GITHUB_REDIRECT_URL[ENV];
|
||||
export const GITHUB_AUTH_TOKEN_KEY = "gh_access_token";
|
||||
export const OPENDBC_SOURCE_REPO = "commaai/opendbc";
|
||||
export const GITHUB_AUTH_TOKEN_KEY = 'gh_access_token';
|
||||
export const OPENDBC_SOURCE_REPO = 'commaai/opendbc';
|
||||
|
||||
export const USE_UNLOGGER =
|
||||
typeof window !== "undefined" && getUrlParameter("unlogger") !== null;
|
||||
export const UNLOGGER_HOST = "http://localhost:8080/unlogger";
|
||||
export const USE_UNLOGGER = typeof window !== 'undefined' && getUrlParameter('unlogger') !== null;
|
||||
export const UNLOGGER_HOST = 'http://localhost:8080/unlogger';
|
||||
|
||||
export const LOGENTRIES_TOKEN = "4bc98019-8277-4fe0-867c-ed21ea843cc5";
|
||||
export const LOGENTRIES_TOKEN = '4bc98019-8277-4fe0-867c-ed21ea843cc5';
|
||||
|
||||
export const PART_SEGMENT_LENGTH = 3;
|
||||
|
||||
|
@ -29,7 +28,7 @@ export const CAN_GRAPH_MAX_POINTS = 5000;
|
|||
export const STREAMING_WINDOW = 60;
|
||||
|
||||
const ENV_EXPLORER_URL = {
|
||||
debug: "http://127.0.0.1:3000/",
|
||||
prod: "https://my.comma.ai/"
|
||||
debug: 'http://127.0.0.1:3000/',
|
||||
prod: 'https://my.comma.ai/'
|
||||
};
|
||||
export const EXPLORER_URL = ENV_EXPLORER_URL[ENV];
|
||||
|
|
63
src/index.js
63
src/index.js
|
@ -1,37 +1,37 @@
|
|||
import Sentry from "./logging/Sentry";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import CommaAuth from "@commaai/my-comma-auth";
|
||||
import { request as Request } from "@commaai/comma-api";
|
||||
import CanExplorer from "./CanExplorer";
|
||||
import AcuraDbc from "./acura-dbc";
|
||||
import { getUrlParameter, modifyQueryParameters } from "./utils/url";
|
||||
import { GITHUB_AUTH_TOKEN_KEY } from "./config";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import CommaAuth from '@commaai/my-comma-auth';
|
||||
import { request as Request } from '@commaai/comma-api';
|
||||
import Sentry from './logging/Sentry';
|
||||
import CanExplorer from './CanExplorer';
|
||||
import AcuraDbc from './acura-dbc';
|
||||
import { getUrlParameter, modifyQueryParameters } from './utils/url';
|
||||
import { GITHUB_AUTH_TOKEN_KEY } from './config';
|
||||
import {
|
||||
fetchPersistedDbc,
|
||||
fetchPersistedGithubAuthToken,
|
||||
persistGithubAuthToken
|
||||
} from "./api/localstorage";
|
||||
import "./index.css";
|
||||
} from './api/localstorage';
|
||||
import './index.css';
|
||||
|
||||
Sentry.init();
|
||||
|
||||
const routeFullName = getUrlParameter("route");
|
||||
let isDemo = !routeFullName;
|
||||
let props = { autoplay: true, isDemo };
|
||||
const routeFullName = getUrlParameter('route');
|
||||
const isDemo = !routeFullName;
|
||||
const props = { autoplay: true, isDemo };
|
||||
let persistedDbc = null;
|
||||
|
||||
if (routeFullName) {
|
||||
const [dongleId, route] = routeFullName.split("|");
|
||||
const [dongleId, route] = routeFullName.split('|');
|
||||
props.dongleId = dongleId;
|
||||
props.name = route;
|
||||
|
||||
persistedDbc = fetchPersistedDbc(routeFullName);
|
||||
|
||||
let max = getUrlParameter("max"),
|
||||
url = getUrlParameter("url"),
|
||||
exp = getUrlParameter("exp"),
|
||||
sig = getUrlParameter("sig");
|
||||
const max = getUrlParameter('max');
|
||||
const url = getUrlParameter('url');
|
||||
const exp = getUrlParameter('exp');
|
||||
const sig = getUrlParameter('sig');
|
||||
|
||||
if (max) {
|
||||
props.max = max;
|
||||
|
@ -47,15 +47,14 @@ if (routeFullName) {
|
|||
}
|
||||
props.isLegacyShare = max && url && !exp && !sig;
|
||||
props.isShare = max && url && exp && sig;
|
||||
} else if (getUrlParameter("demo")) {
|
||||
} else if (getUrlParameter('demo')) {
|
||||
props.max = 12;
|
||||
props.url =
|
||||
"https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47";
|
||||
props.name = "2017-06-12--18-51-47";
|
||||
props.dongleId = "cb38263377b873ee";
|
||||
props.url = 'https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47';
|
||||
props.name = '2017-06-12--18-51-47';
|
||||
props.dongleId = 'cb38263377b873ee';
|
||||
props.dbc = AcuraDbc;
|
||||
props.isDemo = true;
|
||||
props.dbcFilename = "acura_ilx_2016_can.dbc";
|
||||
props.dbcFilename = 'acura_ilx_2016_can.dbc';
|
||||
|
||||
// lots of 404s on this one
|
||||
// props.max = 752;
|
||||
|
@ -97,17 +96,17 @@ async function init() {
|
|||
if (token) {
|
||||
Request.configure(token);
|
||||
}
|
||||
ReactDOM.render(<CanExplorer {...props} />, document.getElementById("root"));
|
||||
ReactDOM.render(<CanExplorer {...props} />, document.getElementById('root'));
|
||||
}
|
||||
|
||||
if (routeFullName || isDemo) {
|
||||
init();
|
||||
} else {
|
||||
const img = document.createElement("img");
|
||||
img.src = process.env.PUBLIC_URL + "/img/cabana.jpg";
|
||||
img.style.width = "100%";
|
||||
const comment = document.createComment("7/6/17");
|
||||
const img = document.createElement('img');
|
||||
img.src = `${process.env.PUBLIC_URL}/img/cabana.jpg`;
|
||||
img.style.width = '100%';
|
||||
const comment = document.createComment('7/6/17');
|
||||
|
||||
document.getElementById("root").appendChild(img);
|
||||
document.getElementById("root").appendChild(comment);
|
||||
document.getElementById('root').appendChild(img);
|
||||
document.getElementById('root').appendChild(comment);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import LogEntries from "./LogEntries";
|
||||
import { LOGENTRIES_TOKEN } from "../config";
|
||||
import LogEntries from './LogEntries';
|
||||
import { LOGENTRIES_TOKEN } from '../config';
|
||||
|
||||
class CloudLog {
|
||||
constructor() {
|
||||
|
@ -15,8 +15,8 @@ class CloudLog {
|
|||
this.context.update(obj);
|
||||
}
|
||||
|
||||
emit(message, level = "log") {
|
||||
if (typeof global.__JEST__ !== "undefined") {
|
||||
emit(message, level = 'log') {
|
||||
if (typeof global.__JEST__ !== 'undefined') {
|
||||
// Don't log in testing environment
|
||||
return;
|
||||
}
|
||||
|
@ -25,14 +25,14 @@ class CloudLog {
|
|||
ctx: this.context,
|
||||
created: new Date().getTime() / 1000,
|
||||
msg: message,
|
||||
src: "JSCloudLog"
|
||||
src: 'JSCloudLog'
|
||||
};
|
||||
|
||||
if (level === "log") {
|
||||
if (level === 'log') {
|
||||
LogEntries.log(entry);
|
||||
} else if (level === "warn") {
|
||||
} else if (level === 'warn') {
|
||||
LogEntries.warn(entry);
|
||||
} else if (level === "error") {
|
||||
} else if (level === 'error') {
|
||||
LogEntries.error(entry);
|
||||
}
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ class CloudLog {
|
|||
}
|
||||
|
||||
warn(message) {
|
||||
this.emit(message, "warn");
|
||||
this.emit(message, 'warn');
|
||||
}
|
||||
|
||||
error(message) {
|
||||
this.emit(message, "error");
|
||||
this.emit(message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import Raven from "raven-js";
|
||||
import Raven from 'raven-js';
|
||||
|
||||
function init() {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
const opts = {};
|
||||
|
||||
if (typeof __webpack_hash__ !== "undefined") {
|
||||
opts["release"] = __webpack_hash__; // eslint-disable-line no-undef
|
||||
if (typeof __webpack_hash__ !== 'undefined') {
|
||||
opts.release = __webpack_hash__; // eslint-disable-line no-undef
|
||||
}
|
||||
|
||||
Raven.config(
|
||||
"https://50006e5d91894f508dd288bbbf4585a6@sentry.io/185303",
|
||||
'https://50006e5d91894f508dd288bbbf4585a6@sentry.io/185303',
|
||||
opts
|
||||
).install();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const Uint64BE = require("int64-buffer").Uint64BE;
|
||||
const { Uint64BE } = require('int64-buffer');
|
||||
|
||||
export function formatForMsg(msg) {
|
||||
return { bstart: 0, bend: 15 };
|
||||
|
@ -7,7 +7,7 @@ export function formatForMsg(msg) {
|
|||
export function formatMsgDec(msg) {
|
||||
const { bstart, bend } = formatForMsg(msg);
|
||||
const uint = Uint64BE(msg[1]);
|
||||
var tt = "0" + uint.toString(2);
|
||||
let tt = `0${uint.toString(2)}`;
|
||||
tt = tt.substring(0, tt.length - (63 - bend));
|
||||
tt = tt.substring(tt.length - (bend - bstart) - 1);
|
||||
return [msg[0], parseInt(tt, 2)];
|
||||
|
@ -20,17 +20,17 @@ export function uint64BEToHex(int64) {
|
|||
export function int64BufferToPrettyHexStr(buffer) {
|
||||
const uint = Uint64BE(buffer);
|
||||
let hex = uint.toString(16);
|
||||
if (hex.length === 1) hex = "0" + hex;
|
||||
let hexParts = hex.match(/.{1,2}/g);
|
||||
if (hex.length === 1) hex = `0${hex}`;
|
||||
const hexParts = hex.match(/.{1,2}/g);
|
||||
|
||||
return hexParts.join(" ");
|
||||
return hexParts.join(' ');
|
||||
}
|
||||
|
||||
export function formatMsgHex(msg) {
|
||||
const uint = Uint64BE(msg[1]);
|
||||
let hex = uint.toString(16);
|
||||
if (hex.length === 1) hex = "0" + hex;
|
||||
let hexParts = hex.match(/.{1,2}/g);
|
||||
if (hex.length === 1) hex = `0${hex}`;
|
||||
const hexParts = hex.match(/.{1,2}/g);
|
||||
|
||||
return [msg[0], hexParts.join(" ")];
|
||||
return [msg[0], hexParts.join(' ')];
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import rightPad from "right-pad";
|
||||
import CloudLog from "../../logging/CloudLog";
|
||||
import Signal from "./signal";
|
||||
import Frame from "./frame";
|
||||
import BoardUnit from "./BoardUnit";
|
||||
import DbcUtils from "../../utils/dbc";
|
||||
import * as LogSignals from "./logSignals";
|
||||
import rightPad from 'right-pad';
|
||||
import CloudLog from '../../logging/CloudLog';
|
||||
import Signal from './signal';
|
||||
import Frame from './frame';
|
||||
import BoardUnit from './BoardUnit';
|
||||
import DbcUtils from '../../utils/dbc';
|
||||
import * as LogSignals from './logSignals';
|
||||
|
||||
const UINT64 = require("cuint").UINT64;
|
||||
const { UINT64 } = require('cuint');
|
||||
|
||||
const DBC_COMMENT_RE = /^CM_ *"(.*)";/;
|
||||
const DBC_COMMENT_MULTI_LINE_RE = /^CM_ *"(.*)/;
|
||||
|
@ -34,17 +34,16 @@ const BOARD_UNIT_COMMENT_RE = /^CM_ BU_ *(\w+) *"(.*)";/;
|
|||
const BOARD_UNIT_COMMENT_MULTI_LINE_RE = /^CM_ BU_ *(\w+) *"(.*)/;
|
||||
|
||||
// Follow ups are used to parse multi-line comment definitions
|
||||
const FOLLOW_UP_DBC_COMMENT = "FollowUpDbcComment";
|
||||
const FOLLOW_UP_SIGNAL_COMMENT = "FollowUpSignalComment";
|
||||
const FOLLOW_UP_MSG_COMMENT = "FollowUpMsgComment";
|
||||
const FOLLOW_UP_BOARD_UNIT_COMMENT = "FollowUpBoardUnitComment";
|
||||
const FOLLOW_UP_DBC_COMMENT = 'FollowUpDbcComment';
|
||||
const FOLLOW_UP_SIGNAL_COMMENT = 'FollowUpSignalComment';
|
||||
const FOLLOW_UP_MSG_COMMENT = 'FollowUpMsgComment';
|
||||
const FOLLOW_UP_BOARD_UNIT_COMMENT = 'FollowUpBoardUnitComment';
|
||||
|
||||
function floatOrInt(numericStr) {
|
||||
if (Number.isInteger(numericStr)) {
|
||||
return parseInt(numericStr, 10);
|
||||
} else {
|
||||
return parseFloat(numericStr);
|
||||
}
|
||||
return parseFloat(numericStr);
|
||||
}
|
||||
|
||||
export function swapOrder(arr, wordSize, gSize) {
|
||||
|
@ -57,7 +56,7 @@ export function swapOrder(arr, wordSize, gSize) {
|
|||
}
|
||||
}
|
||||
|
||||
return swappedWords.join("");
|
||||
return swappedWords.join('');
|
||||
}
|
||||
|
||||
export default class DBC {
|
||||
|
@ -82,14 +81,14 @@ export default class DBC {
|
|||
nextNewFrameName() {
|
||||
const messageNames = [];
|
||||
|
||||
for (let msg of this.messages.values()) {
|
||||
for (const msg of this.messages.values()) {
|
||||
messageNames.push(msg.name);
|
||||
}
|
||||
|
||||
let msgNum = 1,
|
||||
msgName;
|
||||
let msgNum = 1;
|
||||
let msgName;
|
||||
do {
|
||||
msgName = "NEW_MSG_" + msgNum;
|
||||
msgName = `NEW_MSG_${msgNum}`;
|
||||
msgNum++;
|
||||
} while (messageNames.indexOf(msgName) !== -1);
|
||||
|
||||
|
@ -97,15 +96,15 @@ export default class DBC {
|
|||
}
|
||||
|
||||
updateBoardUnits() {
|
||||
const boardUnitNames = this.boardUnits.map(bu => bu.name);
|
||||
const boardUnitNames = this.boardUnits.map((bu) => bu.name);
|
||||
const missingBoardUnits = Array.from(this.messages.entries())
|
||||
.map(([msgId, frame]) => Object.values(frame.signals))
|
||||
.reduce((arr, signals) => arr.concat(signals), [])
|
||||
.map(signal => signal.receiver)
|
||||
.map((signal) => signal.receiver)
|
||||
.reduce((arr, receivers) => arr.concat(receivers), [])
|
||||
.filter((recv, idx, array) => array.indexOf(recv) === idx)
|
||||
.filter(recv => boardUnitNames.indexOf(recv) === -1)
|
||||
.map(recv => new BoardUnit(recv));
|
||||
.filter((recv) => boardUnitNames.indexOf(recv) === -1)
|
||||
.map((recv) => new BoardUnit(recv));
|
||||
|
||||
this.boardUnits = this.boardUnits.concat(missingBoardUnits);
|
||||
}
|
||||
|
@ -114,57 +113,54 @@ export default class DBC {
|
|||
this.updateBoardUnits();
|
||||
|
||||
let txt = 'VERSION ""\n\n\n';
|
||||
txt += "NS_ :" + this._newSymbols();
|
||||
txt += "\n\nBS_:\n";
|
||||
txt += `NS_ :${this._newSymbols()}`;
|
||||
txt += '\n\nBS_:\n';
|
||||
|
||||
const boardUnitsText = this.boardUnits.map(bu => bu.text()).join(" ");
|
||||
txt += "\nBU_: " + boardUnitsText + "\n\n\n";
|
||||
const boardUnitsText = this.boardUnits.map((bu) => bu.text()).join(' ');
|
||||
txt += `\nBU_: ${boardUnitsText}\n\n\n`;
|
||||
|
||||
const frames = [];
|
||||
for (let frame of this.messages.values()) {
|
||||
for (const frame of this.messages.values()) {
|
||||
frames.push(frame);
|
||||
}
|
||||
txt += frames.map(f => f.text()).join("\n\n") + "\n\n";
|
||||
txt += `${frames.map((f) => f.text()).join('\n\n')}\n\n`;
|
||||
|
||||
const messageTxs = frames
|
||||
.map(f => [f.id, f.transmitters.slice(1)])
|
||||
.map((f) => [f.id, f.transmitters.slice(1)])
|
||||
.filter(([addr, txs]) => txs.length > 0);
|
||||
txt +=
|
||||
messageTxs
|
||||
.map(([addr, txs]) => `BO_TX_BU_ ${addr} : ${txs.join(",")};`)
|
||||
.join("\n") + "\n\n\n";
|
||||
txt += `${messageTxs
|
||||
.map(([addr, txs]) => `BO_TX_BU_ ${addr} : ${txs.join(',')};`)
|
||||
.join('\n')}\n\n\n`;
|
||||
|
||||
txt += this.boardUnits
|
||||
.filter(bu => bu.comment !== null)
|
||||
.map(bu => `CM_ BU_ ${bu.name} "${bu.comment}";`)
|
||||
.join("\n");
|
||||
.filter((bu) => bu.comment !== null)
|
||||
.map((bu) => `CM_ BU_ ${bu.name} "${bu.comment}";`)
|
||||
.join('\n');
|
||||
|
||||
txt += frames
|
||||
.filter(f => f.comment !== null)
|
||||
.map(msg => `CM_ BO_ ${msg.address} "${msg.comment}";`)
|
||||
.join("\n");
|
||||
.filter((f) => f.comment !== null)
|
||||
.map((msg) => `CM_ BO_ ${msg.address} "${msg.comment}";`)
|
||||
.join('\n');
|
||||
|
||||
const signalsByMsgId = frames
|
||||
.map(f => Object.values(f.signals).map(sig => [f.id, sig]))
|
||||
.map((f) => Object.values(f.signals).map((sig) => [f.id, sig]))
|
||||
.reduce((s1, s2) => s1.concat(s2), []);
|
||||
|
||||
txt +=
|
||||
signalsByMsgId
|
||||
.filter(([msgAddr, sig]) => sig.comment !== null)
|
||||
.map(
|
||||
([msgAddr, sig]) => `CM_ SG_ ${msgAddr} ${sig.name} "${sig.comment}";`
|
||||
)
|
||||
.join("\n") + "\n";
|
||||
txt += `${signalsByMsgId
|
||||
.filter(([msgAddr, sig]) => sig.comment !== null)
|
||||
.map(
|
||||
([msgAddr, sig]) => `CM_ SG_ ${msgAddr} ${sig.name} "${sig.comment}";`
|
||||
)
|
||||
.join('\n')}\n`;
|
||||
|
||||
txt +=
|
||||
signalsByMsgId
|
||||
.filter(([msgAddr, sig]) => sig.valueDescriptions.size > 0)
|
||||
.map(([msgAddr, sig]) => sig.valueDescriptionText(msgAddr))
|
||||
.join("\n") + "\n";
|
||||
txt += `${signalsByMsgId
|
||||
.filter(([msgAddr, sig]) => sig.valueDescriptions.size > 0)
|
||||
.map(([msgAddr, sig]) => sig.valueDescriptionText(msgAddr))
|
||||
.join('\n')}\n`;
|
||||
|
||||
txt += this.comments.map(comment => `CM_ "${comment}";`).join("\n");
|
||||
txt += this.comments.map((comment) => `CM_ "${comment}";`).join('\n');
|
||||
|
||||
return txt.trim() + "\n";
|
||||
return `${txt.trim()}\n`;
|
||||
}
|
||||
|
||||
getMessageName(msgId) {
|
||||
|
@ -218,11 +214,11 @@ export default class DBC {
|
|||
const warnings = [];
|
||||
const messages = new Map();
|
||||
let boardUnits = [];
|
||||
let valueTables = new Map();
|
||||
const valueTables = new Map();
|
||||
let id = 0;
|
||||
let followUp = null;
|
||||
|
||||
const lines = dbcString.split("\n");
|
||||
const lines = dbcString.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i].trim();
|
||||
|
||||
|
@ -230,7 +226,7 @@ export default class DBC {
|
|||
|
||||
if (followUp != null) {
|
||||
const { type, data } = followUp;
|
||||
line = line.replace(/" *;/, "");
|
||||
line = line.replace(/" *;/, '');
|
||||
let followUpLine = `\n${line.substr(0, line.length)}`;
|
||||
if (line.indexOf('"') !== -1) {
|
||||
followUp = null;
|
||||
|
@ -248,13 +244,12 @@ export default class DBC {
|
|||
} else if (type === FOLLOW_UP_DBC_COMMENT) {
|
||||
// const comment = data;
|
||||
const partialComment = this.comments[this.comments.length - 1];
|
||||
this.comments[this.comments.length - 1] =
|
||||
partialComment + followUpLine;
|
||||
this.comments[this.comments.length - 1] = partialComment + followUpLine;
|
||||
}
|
||||
}
|
||||
|
||||
if (line.indexOf("BO_ ") === 0) {
|
||||
let matches = line.match(MSG_RE);
|
||||
if (line.indexOf('BO_ ') === 0) {
|
||||
const matches = line.match(MSG_RE);
|
||||
if (matches === null) {
|
||||
warnings.push(
|
||||
`failed to parse message definition on line ${i + 1} -- ${line}`
|
||||
|
@ -271,7 +266,7 @@ export default class DBC {
|
|||
transmitters: [transmitter]
|
||||
});
|
||||
messages.set(id, frame);
|
||||
} else if (line.indexOf("SG_") === 0) {
|
||||
} else if (line.indexOf('SG_') === 0) {
|
||||
let matches = line.match(SIGNAL_RE);
|
||||
|
||||
if (matches === null) {
|
||||
|
@ -304,12 +299,12 @@ export default class DBC {
|
|||
startBit = parseInt(startBit, 10);
|
||||
size = parseInt(size, 10);
|
||||
isLittleEndian = parseInt(isLittleEndian, 10) === 1;
|
||||
isSigned = isSigned === "-";
|
||||
isSigned = isSigned === '-';
|
||||
factor = floatOrInt(factor);
|
||||
offset = floatOrInt(offset);
|
||||
min = floatOrInt(min);
|
||||
max = floatOrInt(max);
|
||||
const receiver = receiverStr.split(",").map(s => s.trim());
|
||||
const receiver = receiverStr.split(',').map((s) => s.trim());
|
||||
|
||||
const signalProperties = {
|
||||
name,
|
||||
|
@ -330,35 +325,32 @@ export default class DBC {
|
|||
messages.get(id).signals[name] = signal;
|
||||
} else {
|
||||
CloudLog.warn(
|
||||
"importDbcString: could not add signal: " +
|
||||
name +
|
||||
" due to missing message: " +
|
||||
id
|
||||
`importDbcString: could not add signal: ${name} due to missing message: ${id}`
|
||||
);
|
||||
}
|
||||
} else if (line.indexOf("VAL_ ") === 0) {
|
||||
let matches = line.match(VAL_RE);
|
||||
} else if (line.indexOf('VAL_ ') === 0) {
|
||||
const matches = line.match(VAL_RE);
|
||||
|
||||
if (matches !== null) {
|
||||
let [messageId, signalName, vals] = matches.slice(1);
|
||||
vals = vals
|
||||
.split('"')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0);
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
|
||||
messageId = parseInt(messageId, 10);
|
||||
const msg = messages.get(messageId);
|
||||
const signal = msg.signals[signalName];
|
||||
if (signal === undefined) {
|
||||
warnings.push(
|
||||
`could not find signal for value description on line ${i +
|
||||
1} -- ${line}`
|
||||
`could not find signal for value description on line ${i
|
||||
+ 1} -- ${line}`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
for (let i = 0; i < vals.length; i += 2) {
|
||||
const value = vals[i].trim(),
|
||||
description = vals[i + 1].trim();
|
||||
const value = vals[i].trim();
|
||||
const description = vals[i + 1].trim();
|
||||
signal.valueDescriptions.set(value, description);
|
||||
}
|
||||
} else {
|
||||
|
@ -366,20 +358,20 @@ export default class DBC {
|
|||
`failed to parse value description on line ${i + 1} -- ${line}`
|
||||
);
|
||||
}
|
||||
} else if (line.indexOf("VAL_TABLE_ ") === 0) {
|
||||
let matches = line.match(VAL_TABLE_RE);
|
||||
} else if (line.indexOf('VAL_TABLE_ ') === 0) {
|
||||
const matches = line.match(VAL_TABLE_RE);
|
||||
|
||||
if (matches !== null) {
|
||||
const table = new Map();
|
||||
let [tableName, items] = matches.slice(1);
|
||||
items = items
|
||||
.split('"')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0);
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
|
||||
for (let i = 0; i < items.length; i += 2) {
|
||||
const key = items[i],
|
||||
value = items[i + 1];
|
||||
const key = items[i];
|
||||
const value = items[i + 1];
|
||||
table.set(key, value);
|
||||
}
|
||||
valueTables.set(tableName, table);
|
||||
|
@ -388,8 +380,8 @@ export default class DBC {
|
|||
`failed to parse value table on line ${i + 1} -- ${line}`
|
||||
);
|
||||
}
|
||||
} else if (line.indexOf("BO_TX_BU_ ") === 0) {
|
||||
let matches = line.match(MSG_TRANSMITTER_RE);
|
||||
} else if (line.indexOf('BO_TX_BU_ ') === 0) {
|
||||
const matches = line.match(MSG_TRANSMITTER_RE);
|
||||
|
||||
if (matches !== null) {
|
||||
let [messageId, transmitter] = matches.slice(1);
|
||||
|
@ -400,11 +392,11 @@ export default class DBC {
|
|||
messages.set(messageId, msg);
|
||||
} else {
|
||||
warnings.push(
|
||||
`failed to parse message transmitter definition on line ${i +
|
||||
1} -- ${line}`
|
||||
`failed to parse message transmitter definition on line ${i
|
||||
+ 1} -- ${line}`
|
||||
);
|
||||
}
|
||||
} else if (line.indexOf("CM_ SG_ ") === 0) {
|
||||
} else if (line.indexOf('CM_ SG_ ') === 0) {
|
||||
let matches = line.match(SIGNAL_COMMENT_RE);
|
||||
let hasFollowUp = false;
|
||||
if (matches === null) {
|
||||
|
@ -423,8 +415,8 @@ export default class DBC {
|
|||
messageId = parseInt(messageId, 10);
|
||||
const msg = messages.get(messageId);
|
||||
if (msg === undefined) {
|
||||
warnings.push(`failed to parse signal comment on line ${i +
|
||||
1} -- ${line}:
|
||||
warnings.push(`failed to parse signal comment on line ${i
|
||||
+ 1} -- ${line}:
|
||||
message id ${messageId} does not exist prior to this line`);
|
||||
continue;
|
||||
}
|
||||
|
@ -442,7 +434,7 @@ export default class DBC {
|
|||
if (hasFollowUp) {
|
||||
followUp = { type: FOLLOW_UP_SIGNAL_COMMENT, data: signal };
|
||||
}
|
||||
} else if (line.indexOf("CM_ BO_ ") === 0) {
|
||||
} else if (line.indexOf('CM_ BO_ ') === 0) {
|
||||
let matches = line.match(MESSAGE_COMMENT_RE);
|
||||
let hasFollowUp = false;
|
||||
if (matches === null) {
|
||||
|
@ -464,16 +456,16 @@ export default class DBC {
|
|||
if (hasFollowUp) {
|
||||
followUp = { type: FOLLOW_UP_MSG_COMMENT, data: msg };
|
||||
}
|
||||
} else if (line.indexOf("BU_: ") === 0) {
|
||||
let matches = line.match(BOARD_UNIT_RE);
|
||||
} else if (line.indexOf('BU_: ') === 0) {
|
||||
const matches = line.match(BOARD_UNIT_RE);
|
||||
|
||||
if (matches !== null) {
|
||||
const [boardUnitNameStr] = matches.slice(1);
|
||||
const newBoardUnits = boardUnitNameStr
|
||||
.split(" ")
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0)
|
||||
.map(name => new BoardUnit(name));
|
||||
.split(' ')
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0)
|
||||
.map((name) => new BoardUnit(name));
|
||||
|
||||
boardUnits = boardUnits.concat(newBoardUnits);
|
||||
} else {
|
||||
|
@ -482,7 +474,7 @@ export default class DBC {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
} else if (line.indexOf("CM_ BU_ ") === 0) {
|
||||
} else if (line.indexOf('CM_ BU_ ') === 0) {
|
||||
let matches = line.match(BOARD_UNIT_COMMENT_RE);
|
||||
let hasFollowUp = false;
|
||||
if (matches === null) {
|
||||
|
@ -496,8 +488,8 @@ export default class DBC {
|
|||
}
|
||||
}
|
||||
|
||||
let [boardUnitName, comment] = matches.slice(1);
|
||||
let boardUnit = boardUnits.find(bu => bu.name === boardUnitName);
|
||||
const [boardUnitName, comment] = matches.slice(1);
|
||||
const boardUnit = boardUnits.find((bu) => bu.name === boardUnitName);
|
||||
if (boardUnit) {
|
||||
boardUnit.comment = comment;
|
||||
}
|
||||
|
@ -505,7 +497,7 @@ export default class DBC {
|
|||
if (hasFollowUp) {
|
||||
followUp = { type: FOLLOW_UP_BOARD_UNIT_COMMENT, data: boardUnit };
|
||||
}
|
||||
} else if (line.indexOf("CM_ ") === 0) {
|
||||
} else if (line.indexOf('CM_ ') === 0) {
|
||||
let matches = line.match(DBC_COMMENT_RE);
|
||||
let hasFollowUp = false;
|
||||
if (matches === null) {
|
||||
|
@ -520,7 +512,7 @@ export default class DBC {
|
|||
}
|
||||
}
|
||||
|
||||
let [comment] = matches.slice(1);
|
||||
const [comment] = matches.slice(1);
|
||||
this.comments.push(comment);
|
||||
if (hasFollowUp) {
|
||||
followUp = { type: FOLLOW_UP_DBC_COMMENT, data: comment };
|
||||
|
@ -542,7 +534,9 @@ export default class DBC {
|
|||
|
||||
valueForInt64Signal(signalSpec, hexData) {
|
||||
const blen = hexData.length * 4;
|
||||
let value, startBit, dataBitPos;
|
||||
let value;
|
||||
let startBit;
|
||||
let dataBitPos;
|
||||
|
||||
if (signalSpec.isLittleEndian) {
|
||||
value = UINT64(swapOrder(hexData, 16, 2), 16);
|
||||
|
@ -559,7 +553,7 @@ export default class DBC {
|
|||
return null;
|
||||
}
|
||||
|
||||
let rightHandAnd = UINT64(Math.pow(2, signalSpec.size) - 1);
|
||||
const rightHandAnd = UINT64(Math.pow(2, signalSpec.size) - 1);
|
||||
let ival = value
|
||||
.shiftr(dataBitPos)
|
||||
.and(rightHandAnd)
|
||||
|
@ -573,11 +567,11 @@ export default class DBC {
|
|||
}
|
||||
|
||||
valueForInt32Signal(signalSpec, buf) {
|
||||
var startBit;
|
||||
let startBit;
|
||||
if (signalSpec.isLittleEndian) {
|
||||
startBit = 64 - signalSpec.startBit - signalSpec.size;
|
||||
} else {
|
||||
var bitPos = (-signalSpec.startBit - 1) % 8;
|
||||
let bitPos = (-signalSpec.startBit - 1) % 8;
|
||||
if (bitPos < 0) {
|
||||
bitPos += 8; // mimic python modulo behavior
|
||||
}
|
||||
|
@ -585,8 +579,9 @@ export default class DBC {
|
|||
startBit = Math.floor(signalSpec.startBit / 8) * 8 + bitPos;
|
||||
}
|
||||
|
||||
var shiftAmount, signalValue;
|
||||
let byteOffset = Math.min(4, Math.floor(signalSpec.startBit / 8));
|
||||
let shiftAmount;
|
||||
let signalValue;
|
||||
const byteOffset = Math.min(4, Math.floor(signalSpec.startBit / 8));
|
||||
if (signalSpec.isLittleEndian) {
|
||||
signalValue = buf.readUInt32LE(byteOffset);
|
||||
shiftAmount = signalSpec.startBit - 8 * byteOffset;
|
||||
|
@ -609,17 +604,17 @@ export default class DBC {
|
|||
}
|
||||
const frame = this.getMessageFrame(messageId);
|
||||
|
||||
let buffer = Buffer.from(data);
|
||||
const buffer = Buffer.from(data);
|
||||
let paddedBuffer = buffer;
|
||||
if (buffer.length !== 8) {
|
||||
// pad data it's 64 bits long
|
||||
const paddedDataHex = rightPad(buffer.toString("hex"), 16, "0");
|
||||
paddedBuffer = Buffer.from(paddedDataHex, "hex");
|
||||
const paddedDataHex = rightPad(buffer.toString('hex'), 16, '0');
|
||||
paddedBuffer = Buffer.from(paddedDataHex, 'hex');
|
||||
}
|
||||
const hexData = paddedBuffer.toString("hex");
|
||||
const hexData = paddedBuffer.toString('hex');
|
||||
|
||||
const signalValuesByName = {};
|
||||
Object.values(frame.signals).forEach(signalSpec => {
|
||||
Object.values(frame.signals).forEach((signalSpec) => {
|
||||
let value;
|
||||
if (signalSpec.size > 32) {
|
||||
value = this.valueForInt64Signal(signalSpec, hexData);
|
||||
|
@ -634,15 +629,15 @@ export default class DBC {
|
|||
|
||||
getChffrMetricMappings() {
|
||||
const metricComment = this.comments.find(
|
||||
comment => comment.indexOf("CHFFR_METRIC") === 0
|
||||
(comment) => comment.indexOf('CHFFR_METRIC') === 0
|
||||
);
|
||||
if (!metricComment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return metricComment
|
||||
.split(";")
|
||||
.map(metric => metric.trim().split(" "))
|
||||
.split(';')
|
||||
.map((metric) => metric.trim().split(' '))
|
||||
.reduce(
|
||||
(metrics, [_, messageId, signalName, metricName, factor, offset]) => {
|
||||
metrics[metricName] = {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
function findTimeIndex(entries, time) {
|
||||
return entries.findIndex(e => e.time >= time);
|
||||
return entries.findIndex((e) => e.time >= time);
|
||||
}
|
||||
|
||||
function findRelativeTimeIndex(entries, relTime) {
|
||||
return entries.findIndex(e => e.relTime >= relTime);
|
||||
return entries.findIndex((e) => e.relTime >= relTime);
|
||||
}
|
||||
|
||||
function findSegmentIndices(
|
||||
|
@ -20,17 +20,15 @@ function findSegmentIndices(
|
|||
Returns `[segmentIdxLow, segmentIdxHigh]`
|
||||
(inclusive, exclusive)
|
||||
*/
|
||||
let timeIndexFunc =
|
||||
isRelative === true ? findRelativeTimeIndex : findTimeIndex;
|
||||
const timeIndexFunc = isRelative === true ? findRelativeTimeIndex : findTimeIndex;
|
||||
|
||||
const segmentIdxLow = Math.max(0, timeIndexFunc(entries, segmentTimeLow));
|
||||
|
||||
const upperSegments = entries.slice(segmentIdxLow);
|
||||
let upperSegmentIdxHi = timeIndexFunc(upperSegments, segmentTimeHi);
|
||||
const segmentIdxHi =
|
||||
upperSegmentIdxHi >= 0
|
||||
? upperSegmentIdxHi + segmentIdxLow + 1
|
||||
: entries.length - 1;
|
||||
const upperSegmentIdxHi = timeIndexFunc(upperSegments, segmentTimeHi);
|
||||
const segmentIdxHi = upperSegmentIdxHi >= 0
|
||||
? upperSegmentIdxHi + segmentIdxLow + 1
|
||||
: entries.length - 1;
|
||||
|
||||
return [
|
||||
segmentIdxLow,
|
||||
|
|
|
@ -20,10 +20,10 @@ export default class Frame {
|
|||
}
|
||||
|
||||
nextNewTransmitterName() {
|
||||
let txNum = 1,
|
||||
txName;
|
||||
let txNum = 1;
|
||||
let txName;
|
||||
do {
|
||||
txName = "NEW_TRANSMITTER_" + txNum;
|
||||
txName = `NEW_TRANSMITTER_${txNum}`;
|
||||
txNum++;
|
||||
} while (this.transmitters.indexOf(txName) !== -1);
|
||||
|
||||
|
@ -38,21 +38,20 @@ export default class Frame {
|
|||
|
||||
header() {
|
||||
return (
|
||||
`BO_ ${this.id} ${this.name}: ${this.size} ` +
|
||||
`${this.transmitters[0] || "XXX"}`
|
||||
`BO_ ${this.id} ${this.name}: ${this.size} `
|
||||
+ `${this.transmitters[0] || 'XXX'}`
|
||||
);
|
||||
}
|
||||
|
||||
text() {
|
||||
const signals = Object.values(this.signals)
|
||||
.map(signal => " " + signal.text()) // indent
|
||||
.join("\n");
|
||||
.map((signal) => ` ${signal.text()}`) // indent
|
||||
.join('\n');
|
||||
|
||||
if (signals.length > 0) {
|
||||
return this.header() + "\n" + signals;
|
||||
} else {
|
||||
return this.header();
|
||||
return `${this.header()}\n${signals}`;
|
||||
}
|
||||
return this.header();
|
||||
}
|
||||
|
||||
copy() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Frame from "./frame";
|
||||
import Signal from "./signal";
|
||||
import Frame from './frame';
|
||||
import Signal from './signal';
|
||||
|
||||
export const wheelSpeeds = {
|
||||
FrontLeftWheel: shortSignal({
|
||||
|
@ -82,13 +82,13 @@ export const flags = {
|
|||
Standstill: boolSignal({
|
||||
index: 8
|
||||
}),
|
||||
"CruiseState.Enabled": boolSignal({
|
||||
'CruiseState.Enabled': boolSignal({
|
||||
index: 9
|
||||
}),
|
||||
"CruiseState.Available": boolSignal({
|
||||
'CruiseState.Available': boolSignal({
|
||||
index: 10
|
||||
}),
|
||||
"CruiseState.Standstill": boolSignal({
|
||||
'CruiseState.Standstill': boolSignal({
|
||||
index: 11
|
||||
}),
|
||||
GearShifter: {
|
||||
|
@ -96,7 +96,7 @@ export const flags = {
|
|||
size: 4,
|
||||
unsigned: true
|
||||
},
|
||||
"CruiseState.Speed": charSignal({
|
||||
'CruiseState.Speed': charSignal({
|
||||
index: 2
|
||||
})
|
||||
};
|
||||
|
@ -192,21 +192,21 @@ export const thermalFreeSpace = {
|
|||
};
|
||||
|
||||
export const signalMap = {
|
||||
"CarState:WheelSpeeds": wheelSpeeds,
|
||||
"CarState:Ego": ego,
|
||||
"CarState:Controls": controls,
|
||||
"CarState:Flags": flags,
|
||||
"UbloxGnss:MeasurementReport": ubloxGnss,
|
||||
"Health:Data": health,
|
||||
"Thermal:CPU": thermalCPU,
|
||||
"Thermal:Data": thermalData,
|
||||
"Thermal:FreeSpace": thermalFreeSpace
|
||||
'CarState:WheelSpeeds': wheelSpeeds,
|
||||
'CarState:Ego': ego,
|
||||
'CarState:Controls': controls,
|
||||
'CarState:Flags': flags,
|
||||
'UbloxGnss:MeasurementReport': ubloxGnss,
|
||||
'Health:Data': health,
|
||||
'Thermal:CPU': thermalCPU,
|
||||
'Thermal:Data': thermalData,
|
||||
'Thermal:FreeSpace': thermalFreeSpace
|
||||
};
|
||||
|
||||
const ADDRESS_LIST = [];
|
||||
|
||||
Object.keys(signalMap).forEach(function(name) {
|
||||
Object.keys(signalMap[name]).forEach(function(signal) {
|
||||
Object.keys(signalMap).forEach((name) => {
|
||||
Object.keys(signalMap[name]).forEach((signal) => {
|
||||
signalMap[name][signal] = createSignalEntry({
|
||||
name: signal,
|
||||
...signalMap[name][signal]
|
||||
|
@ -224,7 +224,7 @@ function createSignalEntry(options) {
|
|||
isSigned: !options.unsigned,
|
||||
factor: options.factor || 1,
|
||||
offset: options.offset || 0,
|
||||
unit: options.unit || ""
|
||||
unit: options.unit || ''
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,7 @@ function boolSignal(options) {
|
|||
}
|
||||
|
||||
export function addressForName(name) {
|
||||
var i = ADDRESS_LIST.indexOf(name);
|
||||
const i = ADDRESS_LIST.indexOf(name);
|
||||
if (i === -1) {
|
||||
ADDRESS_LIST.push(name);
|
||||
return ADDRESS_LIST.indexOf(name) + 0x1000;
|
||||
|
@ -282,10 +282,10 @@ export function isLogAddress(address) {
|
|||
}
|
||||
|
||||
export function frameForAddress(address) {
|
||||
let name = nameForAddress(address);
|
||||
const name = nameForAddress(address);
|
||||
return new Frame({
|
||||
id: name,
|
||||
name: name,
|
||||
name,
|
||||
size: 8,
|
||||
signals: signalMap[name]
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DbcUtils from "../../utils/dbc";
|
||||
import DbcUtils from '../../utils/dbc';
|
||||
|
||||
export default class Signal {
|
||||
constructor({
|
||||
|
@ -10,8 +10,8 @@ export default class Signal {
|
|||
isFloat = false,
|
||||
factor = 1,
|
||||
offset = 0,
|
||||
unit = "",
|
||||
receiver = ["XXX"],
|
||||
unit = '',
|
||||
receiver = ['XXX'],
|
||||
comment = null,
|
||||
multiplex = null,
|
||||
min = null,
|
||||
|
@ -45,28 +45,33 @@ export default class Signal {
|
|||
|
||||
const colors = this.generateColors();
|
||||
|
||||
Object.assign(this, { min, max, uid, colors });
|
||||
Object.assign(this, {
|
||||
min,
|
||||
max,
|
||||
uid,
|
||||
colors
|
||||
});
|
||||
}
|
||||
|
||||
text() {
|
||||
const multiplex = this.multiplex ? " " + this.multiplex : "";
|
||||
const multiplex = this.multiplex ? ` ${this.multiplex}` : '';
|
||||
const byteOrder = this.isLittleEndian ? 1 : 0;
|
||||
const signedChar = this.isSigned ? "-" : "+";
|
||||
const signedChar = this.isSigned ? '-' : '+';
|
||||
|
||||
return (
|
||||
`SG_ ${this.name}${multiplex} : ` +
|
||||
`${this.startBit}|${this.size}@${byteOrder}${signedChar}` +
|
||||
` (${this.factor},${this.offset})` +
|
||||
` [${this.min}|${this.max}]` +
|
||||
` "${this.unit}" ${this.receiver}`
|
||||
`SG_ ${this.name}${multiplex} : `
|
||||
+ `${this.startBit}|${this.size}@${byteOrder}${signedChar}`
|
||||
+ ` (${this.factor},${this.offset})`
|
||||
+ ` [${this.min}|${this.max}]`
|
||||
+ ` "${this.unit}" ${this.receiver}`
|
||||
);
|
||||
}
|
||||
|
||||
valueDescriptionText(msgId) {
|
||||
const entryPairs = Array.from(this.valueDescriptions.entries());
|
||||
const values = entryPairs.reduce(
|
||||
(str, [value, desc]) => str + value + ` "${desc}" `,
|
||||
""
|
||||
(str, [value, desc]) => `${str + value} "${desc}" `,
|
||||
''
|
||||
);
|
||||
return `VAL_ ${msgId} ${this.name} ${values};`;
|
||||
}
|
||||
|
@ -76,11 +81,10 @@ export default class Signal {
|
|||
|
||||
if (this.isLittleEndian) {
|
||||
return this.startBit;
|
||||
} else {
|
||||
const lsbBitNumber = this.lsbBitNumber();
|
||||
|
||||
return DbcUtils.matrixBitNumber(lsbBitNumber);
|
||||
}
|
||||
const lsbBitNumber = this.lsbBitNumber();
|
||||
|
||||
return DbcUtils.matrixBitNumber(lsbBitNumber);
|
||||
}
|
||||
|
||||
lsbBitNumber() {
|
||||
|
@ -92,21 +96,19 @@ export default class Signal {
|
|||
msbBitIndex() {
|
||||
if (this.isLittleEndian) {
|
||||
return this.startBit + this.size - 1;
|
||||
} else {
|
||||
return this.startBit;
|
||||
}
|
||||
return this.startBit;
|
||||
}
|
||||
|
||||
littleEndianBitDescription(bitIndex) {
|
||||
const bitRange = [this.startBit, this.startBit + this.size - 1];
|
||||
if (bitIndex < bitRange[0] || bitIndex > bitRange[1]) {
|
||||
return null;
|
||||
} else {
|
||||
const bitNumber = bitIndex - bitRange[0];
|
||||
const isLsb = bitIndex === bitRange[0];
|
||||
const isMsb = bitIndex === bitRange[1];
|
||||
return { bitNumber, isLsb, isMsb };
|
||||
}
|
||||
const bitNumber = bitIndex - bitRange[0];
|
||||
const isLsb = bitIndex === bitRange[0];
|
||||
const isMsb = bitIndex === bitRange[1];
|
||||
return { bitNumber, isLsb, isMsb };
|
||||
}
|
||||
|
||||
bigEndianBitDescription(bitIndex) {
|
||||
|
@ -120,15 +122,19 @@ export default class Signal {
|
|||
|
||||
const isLsb = bitNumber === range[1];
|
||||
const isMsb = bitIndex === this.startBit;
|
||||
return { bitNumber, isLsb, isMsb, range };
|
||||
return {
|
||||
bitNumber,
|
||||
isLsb,
|
||||
isMsb,
|
||||
range
|
||||
};
|
||||
}
|
||||
|
||||
bitDescription(bitIndex) {
|
||||
if (this.isLittleEndian) {
|
||||
return this.littleEndianBitDescription(bitIndex);
|
||||
} else {
|
||||
return this.bigEndianBitDescription(bitIndex);
|
||||
}
|
||||
return this.bigEndianBitDescription(bitIndex);
|
||||
}
|
||||
|
||||
calculateRawRange() {
|
||||
|
@ -150,7 +156,7 @@ export default class Signal {
|
|||
}
|
||||
|
||||
generateColors() {
|
||||
let colors = Array(3);
|
||||
const colors = Array(3);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
colors[i] = Math.floor(Math.random() * 211);
|
||||
}
|
||||
|
@ -160,19 +166,19 @@ export default class Signal {
|
|||
|
||||
equals(otherSignal) {
|
||||
return (
|
||||
otherSignal.name === this.name &&
|
||||
otherSignal.startBit === this.startBit &&
|
||||
otherSignal.size === this.size &&
|
||||
otherSignal.isLittleEndian === this.isLittleEndian &&
|
||||
otherSignal.isSigned === this.isSigned &&
|
||||
otherSignal.isFloat === this.isFloat &&
|
||||
otherSignal.factor === this.factor &&
|
||||
otherSignal.offset === this.offset &&
|
||||
otherSignal.unit === this.unit &&
|
||||
otherSignal.receiver.length === this.receiver.length &&
|
||||
otherSignal.receiver.every((v, i) => v === this.receiver[i]) &&
|
||||
otherSignal.comment === this.comment &&
|
||||
otherSignal.multiplex === this.multiplex
|
||||
otherSignal.name === this.name
|
||||
&& otherSignal.startBit === this.startBit
|
||||
&& otherSignal.size === this.size
|
||||
&& otherSignal.isLittleEndian === this.isLittleEndian
|
||||
&& otherSignal.isSigned === this.isSigned
|
||||
&& otherSignal.isFloat === this.isFloat
|
||||
&& otherSignal.factor === this.factor
|
||||
&& otherSignal.offset === this.offset
|
||||
&& otherSignal.unit === this.unit
|
||||
&& otherSignal.receiver.length === this.receiver.length
|
||||
&& otherSignal.receiver.every((v, i) => v === this.receiver[i])
|
||||
&& otherSignal.comment === this.comment
|
||||
&& otherSignal.multiplex === this.multiplex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import ArrayUtils from "../utils/array";
|
||||
import { CAN_GRAPH_MAX_POINTS } from "../config";
|
||||
import ArrayUtils from '../utils/array';
|
||||
import { CAN_GRAPH_MAX_POINTS } from '../config';
|
||||
|
||||
function _calcGraphData(msg, signalUid, firstCanTime) {
|
||||
if (!msg) return null;
|
||||
|
||||
const signal = Object.values(msg.frame.signals).find(
|
||||
s => s.uid === signalUid
|
||||
(s) => s.uid === signalUid
|
||||
);
|
||||
if (!signal) {
|
||||
console.warn("_calcGraphData: no signal", signalUid, msg);
|
||||
console.warn('_calcGraphData: no signal', signalUid, msg);
|
||||
return null;
|
||||
}
|
||||
let samples = [];
|
||||
let skip = Math.floor(msg.entries.length / CAN_GRAPH_MAX_POINTS);
|
||||
const skip = Math.floor(msg.entries.length / CAN_GRAPH_MAX_POINTS);
|
||||
|
||||
if (skip === 0) {
|
||||
samples = msg.entries;
|
||||
|
@ -29,8 +29,8 @@ function _calcGraphData(msg, signalUid, firstCanTime) {
|
|||
// sorting these doesn't fix the phantom lines
|
||||
let lastEntry = samples[0].relTime;
|
||||
return samples
|
||||
.filter(e => e.signals[signal.name] !== undefined)
|
||||
.map(entry => {
|
||||
.filter((e) => e.signals[signal.name] !== undefined)
|
||||
.map((entry) => {
|
||||
if (entry.relTime - lastEntry > 2) {
|
||||
signalUid = Math.random().toString(36);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ function _calcGraphData(msg, signalUid, firstCanTime) {
|
|||
relTime: entry.relTime,
|
||||
y: entry.signals[signal.name],
|
||||
unit: signal.unit,
|
||||
color: `rgba(${signal.colors.join(",")}, 0.5)`,
|
||||
color: `rgba(${signal.colors.join(',')}, 0.5)`,
|
||||
signalName: signal.name,
|
||||
signalUid
|
||||
};
|
||||
|
@ -49,17 +49,13 @@ function _calcGraphData(msg, signalUid, firstCanTime) {
|
|||
}
|
||||
|
||||
function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
|
||||
const messagesPerPlot = plottedSignals.map(plottedMessages =>
|
||||
plottedMessages.reduce((messages, { messageId, signalUid }) => {
|
||||
messages.push(messageId);
|
||||
return messages;
|
||||
}, [])
|
||||
);
|
||||
const messagesPerPlot = plottedSignals.map((plottedMessages) => plottedMessages.reduce((messages, { messageId, signalUid }) => {
|
||||
messages.push(messageId);
|
||||
return messages;
|
||||
}, []));
|
||||
|
||||
const extendedPlots = messagesPerPlot
|
||||
.map((plottedMessageIds, index) => {
|
||||
return { plottedMessageIds, index };
|
||||
}) // preserve index so we can look up graphData
|
||||
.map((plottedMessageIds, index) => ({ plottedMessageIds, index })) // preserve index so we can look up graphData
|
||||
.filter(({ plottedMessageIds, index }) => {
|
||||
if (index < graphData.length) {
|
||||
let maxGraphTime = 0;
|
||||
|
@ -69,13 +65,11 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
|
|||
}
|
||||
|
||||
return plottedMessageIds.some(
|
||||
messageId =>
|
||||
(messages[messageId].entries.length > 0 && series.length === 0) ||
|
||||
messages[messageId].entries.some(e => e.relTime > maxGraphTime)
|
||||
(messageId) => (messages[messageId].entries.length > 0 && series.length === 0)
|
||||
|| messages[messageId].entries.some((e) => e.relTime > maxGraphTime)
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map(({ plottedMessageIds, index }) => {
|
||||
plottedMessageIds = plottedMessageIds.reduce((arr, messageId) => {
|
||||
|
@ -102,9 +96,10 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
|
|||
const graphDataMaxMessageTimes = plottedMessageIds.reduce(
|
||||
(obj, messageId) => {
|
||||
const signalUids = signalUidsByMessageId[messageId];
|
||||
const maxIndex = ArrayUtils.findIndexRight(series, entry => {
|
||||
return signalUids.indexOf(entry.signalUid) !== -1;
|
||||
});
|
||||
const maxIndex = ArrayUtils.findIndexRight(
|
||||
series,
|
||||
(entry) => signalUids.indexOf(entry.signalUid) !== -1
|
||||
);
|
||||
if (maxIndex) {
|
||||
obj[messageId] = series[maxIndex].relTime;
|
||||
} else if (series.length > 0) {
|
||||
|
@ -121,24 +116,21 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
|
|||
|
||||
let newGraphData = [];
|
||||
plottedMessageIds
|
||||
.map(messageId => {
|
||||
return { messageId, entries: messages[messageId].entries };
|
||||
})
|
||||
.map((messageId) => ({ messageId, entries: messages[messageId].entries }))
|
||||
.filter(
|
||||
(
|
||||
{ messageId, entries } // Filter to only messages with stale graphData
|
||||
) =>
|
||||
entries[entries.length - 1].relTime >
|
||||
graphDataMaxMessageTimes[messageId]
|
||||
) => entries[entries.length - 1].relTime
|
||||
> graphDataMaxMessageTimes[messageId]
|
||||
)
|
||||
.forEach(({ messageId, entries }) => {
|
||||
// Compute and append new graphData
|
||||
let firstNewEntryIdx = entries.findIndex(
|
||||
entry => entry.relTime > graphDataMaxMessageTimes[messageId]
|
||||
const firstNewEntryIdx = entries.findIndex(
|
||||
(entry) => entry.relTime > graphDataMaxMessageTimes[messageId]
|
||||
);
|
||||
|
||||
const newEntries = entries.slice(firstNewEntryIdx);
|
||||
signalUidsByMessageId[messageId].forEach(signalUid => {
|
||||
signalUidsByMessageId[messageId].forEach((signalUid) => {
|
||||
const signalGraphData = _calcGraphData(
|
||||
{
|
||||
...messages[messageId],
|
||||
|
@ -152,12 +144,10 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
|
|||
});
|
||||
});
|
||||
|
||||
const messageIdOutOfBounds =
|
||||
series.length > 0 &&
|
||||
plottedMessageIds.find(
|
||||
messageId =>
|
||||
messages[messageId].entries.length > 0 &&
|
||||
series[0].relTime < messages[messageId].entries[0].relTime
|
||||
const messageIdOutOfBounds = series.length > 0
|
||||
&& plottedMessageIds.find(
|
||||
(messageId) => messages[messageId].entries.length > 0
|
||||
&& series[0].relTime < messages[messageId].entries[0].relTime
|
||||
);
|
||||
graphData[index] = {
|
||||
series: graphData[index].series.concat(newGraphData),
|
||||
|
@ -166,7 +156,7 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
|
|||
|
||||
if (messageIdOutOfBounds) {
|
||||
const graphDataLowerBound = graphData[index].series.findIndex(
|
||||
e => e.relTime > messages[messageIdOutOfBounds].entries[0].relTime
|
||||
(e) => e.relTime > messages[messageIdOutOfBounds].entries[0].relTime
|
||||
);
|
||||
|
||||
if (graphDataLowerBound) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { configure } from "enzyme";
|
||||
import Adapter from "enzyme-adapter-react-16";
|
||||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
configure({ adapter: new Adapter() });
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import { StyleSheet, css } from "aphrodite/no-important";
|
||||
import React from 'react';
|
||||
import { StyleSheet, css } from 'aphrodite/no-important';
|
||||
|
||||
import * as ObjectUtils from "../utils/object";
|
||||
import * as ObjectUtils from '../utils/object';
|
||||
|
||||
function createImageComponent(source, alt, styles) {
|
||||
if (styles === undefined) {
|
||||
|
@ -10,13 +10,13 @@ function createImageComponent(source, alt, styles) {
|
|||
styles = [styles];
|
||||
}
|
||||
|
||||
return props => {
|
||||
return (props) => {
|
||||
let localStyles = styles.slice();
|
||||
if (Array.isArray(props.styles)) {
|
||||
localStyles = localStyles.concat(props.styles);
|
||||
// filter 'styles' from props, which is passed via spread to <img> tag.
|
||||
props = ObjectUtils.fromArray(
|
||||
Object.entries(props).filter(([k, v]) => k !== "styles")
|
||||
Object.entries(props).filter(([k, v]) => k !== 'styles')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -32,36 +32,42 @@ const Styles = StyleSheet.create({
|
|||
height: 24
|
||||
},
|
||||
pointer: {
|
||||
cursor: "pointer"
|
||||
cursor: 'pointer'
|
||||
}
|
||||
});
|
||||
|
||||
const leftArrow = createImageComponent(
|
||||
process.env.PUBLIC_URL + "/img/ic_arrow_left_black_24dp.png",
|
||||
"Left arrow",
|
||||
`${process.env.PUBLIC_URL}/img/ic_arrow_left_black_24dp.png`,
|
||||
'Left arrow',
|
||||
Styles.materialIcon
|
||||
);
|
||||
const rightArrow = createImageComponent(
|
||||
process.env.PUBLIC_URL + "/img/ic_arrow_right_black_24dp.png",
|
||||
"Right arrow",
|
||||
`${process.env.PUBLIC_URL}/img/ic_arrow_right_black_24dp.png`,
|
||||
'Right arrow',
|
||||
Styles.materialIcon
|
||||
);
|
||||
|
||||
const downArrow = createImageComponent(
|
||||
process.env.PUBLIC_URL + "/img/ic_arrow_drop_down_black_24dp.png",
|
||||
"Down arrow",
|
||||
`${process.env.PUBLIC_URL}/img/ic_arrow_drop_down_black_24dp.png`,
|
||||
'Down arrow',
|
||||
Styles.materialIcon
|
||||
);
|
||||
|
||||
const clear = createImageComponent(
|
||||
process.env.PUBLIC_URL + "/img/ic_clear_black_24dp.png",
|
||||
"Clear",
|
||||
`${process.env.PUBLIC_URL}/img/ic_clear_black_24dp.png`,
|
||||
'Clear',
|
||||
[Styles.materialIcon, Styles.pointer]
|
||||
);
|
||||
|
||||
const panda = createImageComponent(
|
||||
process.env.PUBLIC_URL + "/img/panda.png",
|
||||
"Panda",
|
||||
`${process.env.PUBLIC_URL}/img/panda.png`,
|
||||
'Panda',
|
||||
[]
|
||||
);
|
||||
export default { rightArrow, leftArrow, downArrow, clear, panda };
|
||||
export default {
|
||||
rightArrow,
|
||||
leftArrow,
|
||||
downArrow,
|
||||
clear,
|
||||
panda
|
||||
};
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { StyleSheet } from "aphrodite/no-important";
|
||||
import { StyleSheet } from 'aphrodite/no-important';
|
||||
|
||||
export default StyleSheet.create({
|
||||
tab: {
|
||||
display: "inline",
|
||||
display: 'inline',
|
||||
marginRight: 20,
|
||||
cursor: "pointer"
|
||||
cursor: 'pointer'
|
||||
},
|
||||
selectedTab: {
|
||||
borderBottom: "2px solid #000",
|
||||
fontWeight: "bold"
|
||||
borderBottom: '2px solid #000',
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
tabContent: {
|
||||
paddingTop: 20
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
import { StyleSheet } from "aphrodite/no-important";
|
||||
import { StyleSheet } from 'aphrodite/no-important';
|
||||
|
||||
export default StyleSheet.create({
|
||||
root: {
|
||||
flexDirection: "row"
|
||||
flexDirection: 'row'
|
||||
},
|
||||
button: {
|
||||
cursor: "pointer",
|
||||
backgroundColor: "RGB(63, 135, 255)",
|
||||
cursor: 'pointer',
|
||||
backgroundColor: 'RGB(63, 135, 255)',
|
||||
borderRadius: 5,
|
||||
minWidth: 80,
|
||||
paddingLeft: 20,
|
||||
paddingRight: 20,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
color: "white",
|
||||
":hover": {
|
||||
backgroundColor: "RGBA(63, 135, 255, 0.5)"
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: 'white',
|
||||
':hover': {
|
||||
backgroundColor: 'RGBA(63, 135, 255, 0.5)'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
|
||||
// Useful for component testing
|
||||
|
||||
import { css } from "aphrodite";
|
||||
import classNames from "classnames";
|
||||
import { css } from 'aphrodite';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default function() {
|
||||
export default function () {
|
||||
const styles = [];
|
||||
const classes = [];
|
||||
|
||||
[].forEach.call(arguments, it => {
|
||||
[].forEach.call(arguments, (it) => {
|
||||
if (it && it._definition && it._name) styles.push(it);
|
||||
else classes.push(it);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
function findMaxByteStateChangeCount(messages) {
|
||||
return Object.values(messages)
|
||||
.map(m => m.byteStateChangeCounts)
|
||||
.map((m) => m.byteStateChangeCounts)
|
||||
.reduce((counts, countArr) => counts.concat(countArr), []) // flatten arrays
|
||||
.reduce((count1, count2) => (count1 > count2 ? count1 : count2), 0); // find max
|
||||
}
|
||||
|
@ -13,20 +13,20 @@ function addCanMessage(
|
|||
prevMsgEntries,
|
||||
byteStateChangeCountsByMessage
|
||||
) {
|
||||
var { address, busTime, data, bus } = canMessage;
|
||||
var id = bus + ":" + address.toString(16);
|
||||
const {
|
||||
address, busTime, data, bus
|
||||
} = canMessage;
|
||||
const id = `${bus}:${address.toString(16)}`;
|
||||
|
||||
if (messages[id] === undefined)
|
||||
messages[id] = createMessageSpec(dbc, address, id, bus);
|
||||
if (messages[id] === undefined) messages[id] = createMessageSpec(dbc, address, id, bus);
|
||||
|
||||
const prevMsgEntry =
|
||||
messages[id].entries.length > 0
|
||||
? messages[id].entries[messages[id].entries.length - 1]
|
||||
: prevMsgEntries[id] || null;
|
||||
const prevMsgEntry = messages[id].entries.length > 0
|
||||
? messages[id].entries[messages[id].entries.length - 1]
|
||||
: prevMsgEntries[id] || null;
|
||||
|
||||
if (
|
||||
byteStateChangeCountsByMessage[id] &&
|
||||
messages[id].byteStateChangeCounts.every(c => c === 0)
|
||||
byteStateChangeCountsByMessage[id]
|
||||
&& messages[id].byteStateChangeCounts.every((c) => c === 0)
|
||||
) {
|
||||
messages[id].byteStateChangeCounts = byteStateChangeCountsByMessage[id];
|
||||
}
|
||||
|
@ -54,11 +54,11 @@ function createMessageSpec(dbc, address, id, bus) {
|
|||
const size = frame ? frame.size : 8;
|
||||
|
||||
return {
|
||||
address: address,
|
||||
id: id,
|
||||
bus: bus,
|
||||
address,
|
||||
id,
|
||||
bus,
|
||||
entries: [],
|
||||
frame: frame,
|
||||
frame,
|
||||
byteColors: Array(size).fill(0),
|
||||
byteStateChangeCounts: Array(size).fill(0)
|
||||
};
|
||||
|
@ -79,8 +79,8 @@ function determineByteStateChangeTimes(
|
|||
byteStateChangeTimes = Array.from(lastParsedMessage.byteStateChangeTimes);
|
||||
|
||||
for (let i = 0; i < byteStateChangeTimes.length; i++) {
|
||||
const currentData = hexData.substr(i * 2, 2),
|
||||
prevData = lastParsedMessage.hexData.substr(i * 2, 2);
|
||||
const currentData = hexData.substr(i * 2, 2);
|
||||
const prevData = lastParsedMessage.hexData.substr(i * 2, 2);
|
||||
|
||||
if (currentData !== prevData) {
|
||||
byteStateChangeTimes[i] = time;
|
||||
|
@ -104,7 +104,7 @@ function createMessageEntry(
|
|||
signals: dbc.getSignalValues(address, data),
|
||||
time,
|
||||
relTime,
|
||||
hexData: Buffer.from(data).toString("hex"),
|
||||
hexData: Buffer.from(data).toString('hex'),
|
||||
byteStateChangeTimes,
|
||||
updated: Date.now()
|
||||
};
|
||||
|
@ -112,11 +112,11 @@ function createMessageEntry(
|
|||
|
||||
function parseMessage(dbc, time, address, data, timeStart, lastParsedMessage) {
|
||||
let hexData;
|
||||
if (typeof data === "string") {
|
||||
if (typeof data === 'string') {
|
||||
hexData = data;
|
||||
data = Buffer.from(data, "hex");
|
||||
data = Buffer.from(data, 'hex');
|
||||
} else {
|
||||
hexData = Buffer.from(data).toString("hex");
|
||||
hexData = Buffer.from(data).toString('hex');
|
||||
}
|
||||
const msgSpec = dbc.getMessageFrame(address);
|
||||
const msgSize = msgSpec ? msgSpec.size : 8;
|
||||
|
@ -160,13 +160,10 @@ function matrixBitNumber(bigEndianIndex) {
|
|||
|
||||
function setMessageByteColors(message, maxByteStateChangeCount) {
|
||||
message.byteColors = message.byteStateChangeCounts
|
||||
.map(
|
||||
count =>
|
||||
isNaN(count)
|
||||
? 0
|
||||
: Math.min(255, 75 + 180 * (count / maxByteStateChangeCount))
|
||||
)
|
||||
.map(red => "rgb(" + Math.round(red) + ",0,0)");
|
||||
.map((count) => (isNaN(count)
|
||||
? 0
|
||||
: Math.min(255, 75 + 180 * (count / maxByteStateChangeCount))))
|
||||
.map((red) => `rgb(${Math.round(red)},0,0)`);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
export default function debounce(func, wait, immediate) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this,
|
||||
args = arguments;
|
||||
var later = function() {
|
||||
let timeout;
|
||||
return function () {
|
||||
const context = this;
|
||||
const args = arguments;
|
||||
const later = function () {
|
||||
timeout = null;
|
||||
if (!immediate) func.apply(context, args);
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
const callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) func.apply(context, args);
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
const binTimeIntervals = [
|
||||
{
|
||||
seconds: 1,
|
||||
title: "second"
|
||||
title: 'second'
|
||||
},
|
||||
{
|
||||
seconds: 60,
|
||||
title: "minute"
|
||||
title: 'minute'
|
||||
},
|
||||
{
|
||||
seconds: 300,
|
||||
title: "5 minutes"
|
||||
title: '5 minutes'
|
||||
},
|
||||
{
|
||||
seconds: 3600,
|
||||
title: "hour"
|
||||
title: 'hour'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -33,13 +33,13 @@ function prettyBinDuration(samplesDurationSeconds, maxBinCount = 100) {
|
|||
}
|
||||
|
||||
export function binMessages(messageEntries, segmentIndices) {
|
||||
let startIdx = 0,
|
||||
endIdx = messageEntries.length - 1;
|
||||
let startIdx = 0;
|
||||
let endIdx = messageEntries.length - 1;
|
||||
if (segmentIndices && segmentIndices.length === 2) {
|
||||
[startIdx, endIdx] = segmentIndices;
|
||||
}
|
||||
const first = messageEntries[startIdx],
|
||||
last = messageEntries[endIdx];
|
||||
const first = messageEntries[startIdx];
|
||||
const last = messageEntries[endIdx];
|
||||
const binDuration = prettyBinDuration(last.time - first.time);
|
||||
|
||||
const bins = [];
|
||||
|
@ -63,5 +63,5 @@ export function binMessages(messageEntries, segmentIndices) {
|
|||
});
|
||||
}
|
||||
|
||||
return { bins: bins, binDuration };
|
||||
return { bins, binDuration };
|
||||
}
|
||||
|
|
|
@ -7,103 +7,103 @@ const NumpyLoader = (function NumpyLoader() {
|
|||
}
|
||||
|
||||
function readUint16LE(buffer) {
|
||||
var view = new DataView(buffer);
|
||||
var val = view.getUint8(0);
|
||||
const view = new DataView(buffer);
|
||||
let val = view.getUint8(0);
|
||||
val |= view.getUint8(1) << 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
function fromArrayBuffer(buf) {
|
||||
// Check the magic number
|
||||
var magic = asciiDecode(buf.slice(0, 6));
|
||||
if (magic !== "\x93NUMPY") {
|
||||
throw new Error("Bad magic number");
|
||||
const magic = asciiDecode(buf.slice(0, 6));
|
||||
if (magic !== '\x93NUMPY') {
|
||||
throw new Error('Bad magic number');
|
||||
}
|
||||
|
||||
var version = new Uint8Array(buf.slice(6, 8)),
|
||||
headerLength = readUint16LE(buf.slice(8, 10)),
|
||||
headerStr = asciiDecode(buf.slice(10, 10 + headerLength));
|
||||
const version = new Uint8Array(buf.slice(6, 8));
|
||||
const headerLength = readUint16LE(buf.slice(8, 10));
|
||||
const headerStr = asciiDecode(buf.slice(10, 10 + headerLength));
|
||||
const offsetBytes = 10 + headerLength;
|
||||
//rest = buf.slice(10+headerLength); XXX -- This makes a copy!!! https://www.khronos.org/registry/typedarray/specs/latest/#5
|
||||
// rest = buf.slice(10+headerLength); XXX -- This makes a copy!!! https://www.khronos.org/registry/typedarray/specs/latest/#5
|
||||
|
||||
// Hacky conversion of dict literal string to JS Object
|
||||
const info = JSON.parse(
|
||||
headerStr
|
||||
.toLowerCase()
|
||||
.replace("(", "[")
|
||||
.replace("),", "]")
|
||||
.replace('(', '[')
|
||||
.replace('),', ']')
|
||||
.replace(/'/g, '"')
|
||||
.replace(",]", "]")
|
||||
.replace(',]', ']')
|
||||
);
|
||||
|
||||
// Intepret the bytes according to the specified dtype
|
||||
var data;
|
||||
if (info.descr === "|u1") {
|
||||
let data;
|
||||
if (info.descr === '|u1') {
|
||||
data = new Uint8Array(buf, offsetBytes);
|
||||
} else if (info.descr === "|i1") {
|
||||
} else if (info.descr === '|i1') {
|
||||
data = new Int8Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<u2") {
|
||||
} else if (info.descr === '<u2') {
|
||||
data = new Uint16Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<i2") {
|
||||
} else if (info.descr === '<i2') {
|
||||
data = new Int16Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<u4") {
|
||||
} else if (info.descr === '<u4') {
|
||||
data = new Uint32Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<i4") {
|
||||
} else if (info.descr === '<i4') {
|
||||
data = new Int32Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<f4") {
|
||||
} else if (info.descr === '<f4') {
|
||||
data = new Float32Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<f8") {
|
||||
} else if (info.descr === '<f8') {
|
||||
data = new Float64Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<u8") {
|
||||
} else if (info.descr === '<u8') {
|
||||
// 8 byte uint64s
|
||||
data = new Uint8Array(buf, offsetBytes);
|
||||
} else if (info.descr === "<i8") {
|
||||
} else if (info.descr === '<i8') {
|
||||
// 8 byte int64s
|
||||
data = new Uint8Array(buf, offsetBytes);
|
||||
} else if (info.descr === "|s5") {
|
||||
} else if (info.descr === '|s5') {
|
||||
// 5 byte string
|
||||
data = new Uint8Array(buf, offsetBytes);
|
||||
} else if (info.descr === "|s8") {
|
||||
} else if (info.descr === '|s8') {
|
||||
// 8 byte strings
|
||||
data = new Uint8Array(buf, offsetBytes);
|
||||
} else if (info.descr === "|s15") {
|
||||
} else if (info.descr === '|s15') {
|
||||
// 15 byte strings?
|
||||
data = new Uint8Array(buf, offsetBytes);
|
||||
} else {
|
||||
throw new Error("unknown numeric dtype " + info.descr);
|
||||
throw new Error(`unknown numeric dtype ${info.descr}`);
|
||||
}
|
||||
|
||||
return {
|
||||
shape: info.shape,
|
||||
fortran_order: info.fortran_order,
|
||||
data: data
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
function open(file, callback) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
// the file contents have been read as an array buffer
|
||||
var buf = reader.result;
|
||||
var ndarray = fromArrayBuffer(buf);
|
||||
const buf = reader.result;
|
||||
const ndarray = fromArrayBuffer(buf);
|
||||
callback(ndarray);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
function promise(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Do the usual XHR stuff
|
||||
var req = new XMLHttpRequest();
|
||||
req.onload = function() {
|
||||
const req = new XMLHttpRequest();
|
||||
req.onload = function () {
|
||||
// This is called even on 404 etc
|
||||
// so check the status
|
||||
if (req.status == 200) {
|
||||
var buf = req.response; // not responseText
|
||||
var ndarray = fromArrayBuffer(buf);
|
||||
const buf = req.response; // not responseText
|
||||
const ndarray = fromArrayBuffer(buf);
|
||||
resolve(ndarray);
|
||||
} else if (req.status == 404) {
|
||||
console.log("yup");
|
||||
console.log('yup');
|
||||
reject({ is404: true });
|
||||
} else {
|
||||
// Otherwise reject with the status text
|
||||
|
@ -113,22 +113,22 @@ const NumpyLoader = (function NumpyLoader() {
|
|||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
req.onerror = function () {
|
||||
reject(Error('Network Error'));
|
||||
};
|
||||
|
||||
// Make the request
|
||||
req.open("GET", url, true);
|
||||
req.responseType = "arraybuffer";
|
||||
req.open('GET', url, true);
|
||||
req.responseType = 'arraybuffer';
|
||||
req.send(null);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
open: open,
|
||||
promise: promise,
|
||||
fromArrayBuffer: fromArrayBuffer
|
||||
open,
|
||||
promise,
|
||||
fromArrayBuffer
|
||||
};
|
||||
})();
|
||||
}());
|
||||
|
||||
module.exports = NumpyLoader;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export function swapKeysAndValues(obj, f) {
|
||||
return Object.keys(obj).reduce(function(acc, k) {
|
||||
return Object.keys(obj).reduce((acc, k) => {
|
||||
acc[obj[k]] = k;
|
||||
return acc;
|
||||
}, {});
|
||||
|
@ -12,7 +12,6 @@ export function fromArray(arr) {
|
|||
const pairs = arr.map(([k, v]) => ({ [k]: v }));
|
||||
if (pairs.length > 0) {
|
||||
return Object.assign(...pairs);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export function hash(str) {
|
||||
var hash = 5381,
|
||||
i = str.length;
|
||||
let hash = 5381;
|
||||
let i = str.length;
|
||||
|
||||
while (i) {
|
||||
hash = (hash * 33) ^ str.charCodeAt(--i);
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
/* eslint-disable no-restricted-globals*/
|
||||
/* eslint-disable no-restricted-globals */
|
||||
export function objToQuery(obj) {
|
||||
return Object.keys(obj)
|
||||
.map(k => k + "=" + encodeURIComponent(decodeURIComponent(obj[k])))
|
||||
.join("&");
|
||||
.map((k) => `${k}=${encodeURIComponent(decodeURIComponent(obj[k]))}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
export function getUrlParameter(name) {
|
||||
var location = window.location;
|
||||
name = name.replace(/[[]/, "\\[").replace(/[\]]/, "\\]");
|
||||
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
|
||||
var results = regex.exec(location.search);
|
||||
const { location } = window;
|
||||
name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
|
||||
const regex = new RegExp(`[\\?&]${name}=([^&#]*)`);
|
||||
const results = regex.exec(location.search);
|
||||
|
||||
return results === null
|
||||
? null
|
||||
: decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
: decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||
}
|
||||
|
||||
export function modifyQueryParameters({ add, remove = [] }) {
|
||||
var regex = new RegExp("[\\?&]([^&#]+)=([^&#]*)");
|
||||
var results = regex.exec(location.search);
|
||||
const regex = new RegExp('[\\?&]([^&#]+)=([^&#]*)');
|
||||
const results = regex.exec(location.search);
|
||||
|
||||
let params = {};
|
||||
if (results != null) {
|
||||
for (let i = 1; i < results.length - 1; i += 2) {
|
||||
let key = results[i],
|
||||
value = results[i + 1];
|
||||
const key = results[i];
|
||||
const value = results[i + 1];
|
||||
params[key] = value;
|
||||
}
|
||||
for (let key in params) {
|
||||
for (const key in params) {
|
||||
if (remove.indexOf(key) !== -1) {
|
||||
delete params[key];
|
||||
}
|
||||
|
@ -37,5 +37,5 @@ export function modifyQueryParameters({ add, remove = [] }) {
|
|||
params = add;
|
||||
}
|
||||
|
||||
return location.origin + location.pathname + "?" + objToQuery(params);
|
||||
return `${location.origin + location.pathname}?${objToQuery(params)}`;
|
||||
}
|
||||
|
|
|
@ -1,111 +1,121 @@
|
|||
import { createClassFromSpec } from "react-vega";
|
||||
import { createClassFromSpec } from 'react-vega';
|
||||
|
||||
const canHistogramSpec = {
|
||||
$schema: "https://vega.github.io/schema/vega/v3.0.json",
|
||||
$schema: 'https://vega.github.io/schema/vega/v3.0.json',
|
||||
width: 1000,
|
||||
height: 100,
|
||||
padding: 5,
|
||||
|
||||
signals: [
|
||||
{
|
||||
name: "segment"
|
||||
name: 'segment'
|
||||
}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: "binned"
|
||||
name: 'binned'
|
||||
}
|
||||
],
|
||||
|
||||
scales: [
|
||||
{
|
||||
name: "xscale",
|
||||
type: "linear",
|
||||
name: 'xscale',
|
||||
type: 'linear',
|
||||
zero: false,
|
||||
range: "width",
|
||||
domain: { data: "binned", field: "startTime" }
|
||||
range: 'width',
|
||||
domain: { data: 'binned', field: 'startTime' }
|
||||
},
|
||||
{
|
||||
name: "xrelscale",
|
||||
type: "linear",
|
||||
name: 'xrelscale',
|
||||
type: 'linear',
|
||||
zero: false,
|
||||
range: "width",
|
||||
domain: { data: "binned", field: "relStartTime" }
|
||||
range: 'width',
|
||||
domain: { data: 'binned', field: 'relStartTime' }
|
||||
},
|
||||
{
|
||||
name: "yscale",
|
||||
type: "linear",
|
||||
range: "height",
|
||||
name: 'yscale',
|
||||
type: 'linear',
|
||||
range: 'height',
|
||||
round: true,
|
||||
domain: { data: "binned", field: "count" },
|
||||
domain: { data: 'binned', field: 'count' },
|
||||
zero: true,
|
||||
nice: true
|
||||
}
|
||||
],
|
||||
|
||||
axes: [
|
||||
{ orient: "bottom", scale: "xrelscale", zindex: 1, tickCount: 10 },
|
||||
{ orient: "left", scale: "yscale", tickCount: 5, zindex: 1 }
|
||||
{
|
||||
orient: 'bottom',
|
||||
scale: 'xrelscale',
|
||||
zindex: 1,
|
||||
tickCount: 10
|
||||
},
|
||||
{
|
||||
orient: 'left',
|
||||
scale: 'yscale',
|
||||
tickCount: 5,
|
||||
zindex: 1
|
||||
}
|
||||
],
|
||||
|
||||
marks: [
|
||||
{
|
||||
type: "group",
|
||||
name: "histogram",
|
||||
type: 'group',
|
||||
name: 'histogram',
|
||||
interactive: true,
|
||||
encode: {
|
||||
enter: {
|
||||
height: { value: 75 },
|
||||
width: { value: 1000 },
|
||||
fill: { value: "transparent" }
|
||||
fill: { value: 'transparent' }
|
||||
}
|
||||
},
|
||||
signals: [
|
||||
{
|
||||
name: "brush",
|
||||
name: 'brush',
|
||||
value: 0,
|
||||
on: [
|
||||
{
|
||||
events: "@bins:mousedown",
|
||||
update: "[x(), x()]"
|
||||
events: '@bins:mousedown',
|
||||
update: '[x(), x()]'
|
||||
},
|
||||
{
|
||||
events: "[@bins:mousedown, window:mouseup] > window:mousemove!",
|
||||
update: "[brush[0], clamp(x(), 0, width)]"
|
||||
events: '[@bins:mousedown, window:mouseup] > window:mousemove!',
|
||||
update: '[brush[0], clamp(x(), 0, width)]'
|
||||
},
|
||||
{
|
||||
events: { signal: "delta" },
|
||||
events: { signal: 'delta' },
|
||||
update:
|
||||
"clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
|
||||
'clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "anchor",
|
||||
name: 'anchor',
|
||||
value: null,
|
||||
on: [{ events: "@brush:mousedown", update: "slice(brush)" }]
|
||||
on: [{ events: '@brush:mousedown', update: 'slice(brush)' }]
|
||||
},
|
||||
{
|
||||
name: "xdown",
|
||||
name: 'xdown',
|
||||
value: 0,
|
||||
on: [{ events: "@brush:mousedown", update: "x()" }]
|
||||
on: [{ events: '@brush:mousedown', update: 'x()' }]
|
||||
},
|
||||
{
|
||||
name: "delta",
|
||||
name: 'delta',
|
||||
value: 0,
|
||||
on: [
|
||||
{
|
||||
events: "[@brush:mousedown, window:mouseup] > window:mousemove!",
|
||||
update: "x() - xdown"
|
||||
events: '[@brush:mousedown, window:mouseup] > window:mousemove!',
|
||||
update: 'x() - xdown'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "segment",
|
||||
push: "outer",
|
||||
name: 'segment',
|
||||
push: 'outer',
|
||||
on: [
|
||||
{
|
||||
events: { signal: "brush" },
|
||||
events: { signal: 'brush' },
|
||||
update: "span(brush) ? invert('xscale', brush) : null"
|
||||
}
|
||||
]
|
||||
|
@ -113,72 +123,72 @@ const canHistogramSpec = {
|
|||
],
|
||||
marks: [
|
||||
{
|
||||
type: "rect",
|
||||
type: 'rect',
|
||||
interactive: true,
|
||||
from: { data: "binned" },
|
||||
name: "bins",
|
||||
from: { data: 'binned' },
|
||||
name: 'bins',
|
||||
encode: {
|
||||
update: {
|
||||
x: { scale: "xscale", field: "startTime" },
|
||||
x: { scale: 'xscale', field: 'startTime' },
|
||||
x2: {
|
||||
scale: "xscale",
|
||||
field: "endTime",
|
||||
scale: 'xscale',
|
||||
field: 'endTime',
|
||||
offset: 0
|
||||
},
|
||||
y: { scale: "yscale", field: "count" },
|
||||
y2: { scale: "yscale", value: 0 },
|
||||
fill: { value: "steelblue" }
|
||||
y: { scale: 'yscale', field: 'count' },
|
||||
y2: { scale: 'yscale', value: 0 },
|
||||
fill: { value: 'steelblue' }
|
||||
},
|
||||
hover: {
|
||||
fill: { value: "goldenrod" },
|
||||
cursor: { value: "ew-resize" }
|
||||
fill: { value: 'goldenrod' },
|
||||
cursor: { value: 'ew-resize' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "rect",
|
||||
type: 'rect',
|
||||
interactive: true,
|
||||
name: "brush",
|
||||
name: 'brush',
|
||||
encode: {
|
||||
enter: {
|
||||
y: { value: 0 },
|
||||
height: { value: 100 },
|
||||
fill: { value: "#333" },
|
||||
fill: { value: '#333' },
|
||||
fillOpacity: { value: 0.2 }
|
||||
},
|
||||
update: {
|
||||
x: { signal: "brush[0]" },
|
||||
x2: { signal: "brush[1]" }
|
||||
x: { signal: 'brush[0]' },
|
||||
x2: { signal: 'brush[1]' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "rect",
|
||||
type: 'rect',
|
||||
interactive: false,
|
||||
encode: {
|
||||
enter: {
|
||||
y: { value: 0 },
|
||||
height: { value: 100 },
|
||||
width: { value: 2 },
|
||||
fill: { value: "firebrick" }
|
||||
fill: { value: 'firebrick' }
|
||||
},
|
||||
update: {
|
||||
x: { signal: "brush[0]" }
|
||||
x: { signal: 'brush[0]' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "rect",
|
||||
type: 'rect',
|
||||
interactive: false,
|
||||
encode: {
|
||||
enter: {
|
||||
y: { value: 0 },
|
||||
height: { value: 100 },
|
||||
width: { value: 2 },
|
||||
fill: { value: "firebrick" }
|
||||
fill: { value: 'firebrick' }
|
||||
},
|
||||
update: {
|
||||
x: { signal: "brush[1]" }
|
||||
x: { signal: 'brush[1]' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
$schema: "https://vega.github.io/schema/vega/v5.6.json",
|
||||
$schema: 'https://vega.github.io/schema/vega/v5.6.json',
|
||||
width: 400,
|
||||
height: 200,
|
||||
padding: {
|
||||
|
@ -10,166 +10,166 @@ export default {
|
|||
},
|
||||
signals: [
|
||||
{
|
||||
name: "tipTime",
|
||||
name: 'tipTime',
|
||||
on: [
|
||||
{
|
||||
events: "mousemove",
|
||||
events: 'mousemove',
|
||||
update: "invert('xrelscale', x())"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "clickTime",
|
||||
name: 'clickTime',
|
||||
on: [
|
||||
{
|
||||
events: "click",
|
||||
events: 'click',
|
||||
update: "invert('xrelscale', x())"
|
||||
}
|
||||
]
|
||||
},
|
||||
{ name: "videoTime" },
|
||||
{ name: 'videoTime' },
|
||||
{
|
||||
name: "segment",
|
||||
value: { data: "table", field: "relTime" }
|
||||
name: 'segment',
|
||||
value: { data: 'table', field: 'relTime' }
|
||||
}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: "table"
|
||||
name: 'table'
|
||||
},
|
||||
{
|
||||
name: "segment"
|
||||
name: 'segment'
|
||||
},
|
||||
{
|
||||
name: "tooltip",
|
||||
source: "table",
|
||||
name: 'tooltip',
|
||||
source: 'table',
|
||||
transform: [
|
||||
{
|
||||
type: "filter",
|
||||
expr: "abs(datum.relTime - tipTime) <= 0.01"
|
||||
type: 'filter',
|
||||
expr: 'abs(datum.relTime - tipTime) <= 0.01'
|
||||
},
|
||||
{
|
||||
type: "aggregate",
|
||||
fields: ["relTime", "y", "unit"],
|
||||
ops: ["min", "argmin", "argmin"],
|
||||
as: ["min", "argmin", "argmin"]
|
||||
type: 'aggregate',
|
||||
fields: ['relTime', 'y', 'unit'],
|
||||
ops: ['min', 'argmin', 'argmin'],
|
||||
as: ['min', 'argmin', 'argmin']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "ySegmentScale",
|
||||
source: "table",
|
||||
name: 'ySegmentScale',
|
||||
source: 'table',
|
||||
transform: [
|
||||
{
|
||||
type: "filter",
|
||||
type: 'filter',
|
||||
expr:
|
||||
"length(segment) != 2 || (datum.relTime >= segment[0] && datum.relTime <= segment[1])"
|
||||
'length(segment) != 2 || (datum.relTime >= segment[0] && datum.relTime <= segment[1])'
|
||||
},
|
||||
{ type: "extent", field: "y", signal: "ySegment" }
|
||||
{ type: 'extent', field: 'y', signal: 'ySegment' }
|
||||
]
|
||||
}
|
||||
],
|
||||
scales: [
|
||||
{
|
||||
name: "xscale",
|
||||
type: "linear",
|
||||
range: "width",
|
||||
domain: { data: "table", field: "x" },
|
||||
name: 'xscale',
|
||||
type: 'linear',
|
||||
range: 'width',
|
||||
domain: { data: 'table', field: 'x' },
|
||||
zero: false
|
||||
},
|
||||
{
|
||||
name: "xrelscale",
|
||||
type: "linear",
|
||||
range: "width",
|
||||
domain: { data: "table", field: "relTime" },
|
||||
name: 'xrelscale',
|
||||
type: 'linear',
|
||||
range: 'width',
|
||||
domain: { data: 'table', field: 'relTime' },
|
||||
zero: false,
|
||||
clamp: true,
|
||||
domainRaw: { signal: "segment" }
|
||||
domainRaw: { signal: 'segment' }
|
||||
},
|
||||
{
|
||||
name: "yscale",
|
||||
type: "linear",
|
||||
range: "height",
|
||||
name: 'yscale',
|
||||
type: 'linear',
|
||||
range: 'height',
|
||||
clamp: true,
|
||||
zero: false,
|
||||
domain: { signal: "ySegment" }
|
||||
domain: { signal: 'ySegment' }
|
||||
},
|
||||
{
|
||||
name: "color",
|
||||
type: "ordinal",
|
||||
domain: { data: "table", field: "color" },
|
||||
range: { data: "table", field: "color" }
|
||||
name: 'color',
|
||||
type: 'ordinal',
|
||||
domain: { data: 'table', field: 'color' },
|
||||
range: { data: 'table', field: 'color' }
|
||||
}
|
||||
],
|
||||
axes: [
|
||||
{ orient: "bottom", scale: "xrelscale", labelOverlap: true },
|
||||
{ orient: "left", scale: "yscale" }
|
||||
{ orient: 'bottom', scale: 'xrelscale', labelOverlap: true },
|
||||
{ orient: 'left', scale: 'yscale' }
|
||||
],
|
||||
marks: [
|
||||
{
|
||||
type: "group",
|
||||
name: "plot",
|
||||
type: 'group',
|
||||
name: 'plot',
|
||||
interactive: true,
|
||||
encode: {
|
||||
enter: {
|
||||
width: { signal: "width" },
|
||||
height: { signal: "height" },
|
||||
fill: { value: "transparent" }
|
||||
width: { signal: 'width' },
|
||||
height: { signal: 'height' },
|
||||
fill: { value: 'transparent' }
|
||||
}
|
||||
},
|
||||
signals: [
|
||||
{
|
||||
name: "brush",
|
||||
name: 'brush',
|
||||
value: 0,
|
||||
on: [
|
||||
{
|
||||
events: "@boundingRect:mousedown",
|
||||
update: "[x(), x()]"
|
||||
events: '@boundingRect:mousedown',
|
||||
update: '[x(), x()]'
|
||||
},
|
||||
{
|
||||
events:
|
||||
"[@boundingRect:mousedown, window:mouseup] > window:mousemove!",
|
||||
update: "[brush[0], clamp(x(), 0, width)]"
|
||||
'[@boundingRect:mousedown, window:mouseup] > window:mousemove!',
|
||||
update: '[brush[0], clamp(x(), 0, width)]'
|
||||
},
|
||||
{
|
||||
events: { signal: "delta" },
|
||||
events: { signal: 'delta' },
|
||||
update:
|
||||
"clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
|
||||
'clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "anchor",
|
||||
name: 'anchor',
|
||||
value: null,
|
||||
on: [{ events: "@brush:mousedown", update: "slice(brush)" }]
|
||||
on: [{ events: '@brush:mousedown', update: 'slice(brush)' }]
|
||||
},
|
||||
{
|
||||
name: "xdown",
|
||||
name: 'xdown',
|
||||
value: 0,
|
||||
on: [{ events: "@brush:mousedown", update: "x()" }]
|
||||
on: [{ events: '@brush:mousedown', update: 'x()' }]
|
||||
},
|
||||
{
|
||||
name: "xup",
|
||||
name: 'xup',
|
||||
value: 0,
|
||||
on: [{ events: "@brush:mouseup", update: "x()" }]
|
||||
on: [{ events: '@brush:mouseup', update: 'x()' }]
|
||||
},
|
||||
{
|
||||
name: "delta",
|
||||
name: 'delta',
|
||||
value: 0,
|
||||
on: [
|
||||
{
|
||||
events: "[@brush:mousedown, window:mouseup] > window:mousemove!",
|
||||
update: "x() - xdown"
|
||||
events: '[@brush:mousedown, window:mouseup] > window:mousemove!',
|
||||
update: 'x() - xdown'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "segment",
|
||||
push: "outer",
|
||||
name: 'segment',
|
||||
push: 'outer',
|
||||
on: [
|
||||
{
|
||||
events: "window:mouseup",
|
||||
events: 'window:mouseup',
|
||||
update:
|
||||
"span(brush) && span(brush) > 15 ? invert('xrelscale', brush) : segment"
|
||||
}
|
||||
|
@ -178,50 +178,50 @@ export default {
|
|||
],
|
||||
marks: [
|
||||
{
|
||||
type: "group",
|
||||
type: 'group',
|
||||
from: {
|
||||
facet: {
|
||||
name: "series",
|
||||
data: "table",
|
||||
groupby: "signalUid"
|
||||
name: 'series',
|
||||
data: 'table',
|
||||
groupby: 'signalUid'
|
||||
}
|
||||
},
|
||||
marks: {
|
||||
type: "line",
|
||||
name: "lineMark",
|
||||
from: { data: "series" },
|
||||
type: 'line',
|
||||
name: 'lineMark',
|
||||
from: { data: 'series' },
|
||||
interactive: true,
|
||||
encode: {
|
||||
update: {
|
||||
interpolate: { value: "step" },
|
||||
x: { scale: "xrelscale", field: "relTime" },
|
||||
y: { scale: "yscale", field: "y" }
|
||||
interpolate: { value: 'step' },
|
||||
x: { scale: 'xrelscale', field: 'relTime' },
|
||||
y: { scale: 'yscale', field: 'y' }
|
||||
},
|
||||
hover: {
|
||||
fillOpacity: { value: 0.5 }
|
||||
},
|
||||
enter: {
|
||||
clip: { value: true },
|
||||
stroke: { scale: "color", field: "color" },
|
||||
stroke: { scale: 'color', field: 'color' },
|
||||
strokeWidth: { value: 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "rect",
|
||||
type: 'rect',
|
||||
interactive: true,
|
||||
name: "brush",
|
||||
name: 'brush',
|
||||
encode: {
|
||||
enter: {
|
||||
y: { value: 0 },
|
||||
height: { signal: "height" },
|
||||
fill: { value: "#333" },
|
||||
height: { signal: 'height' },
|
||||
fill: { value: '#333' },
|
||||
fillOpacity: { value: 0.2 }
|
||||
},
|
||||
update: {
|
||||
x: { signal: "brush[0]" },
|
||||
x2: { signal: "brush[1]" }
|
||||
x: { signal: 'brush[0]' },
|
||||
x2: { signal: 'brush[1]' }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -256,61 +256,61 @@ export default {
|
|||
// }
|
||||
// },
|
||||
{
|
||||
type: "rule",
|
||||
type: 'rule',
|
||||
encode: {
|
||||
update: {
|
||||
y: { value: 0 },
|
||||
y2: { field: { group: "height" } },
|
||||
stroke: { value: "#000" },
|
||||
y2: { field: { group: 'height' } },
|
||||
stroke: { value: '#000' },
|
||||
strokeWidth: { value: 2 },
|
||||
x: {
|
||||
scale: "xrelscale",
|
||||
signal: "videoTime",
|
||||
scale: 'xrelscale',
|
||||
signal: 'videoTime',
|
||||
offset: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "symbol",
|
||||
from: { data: "tooltip" },
|
||||
type: 'symbol',
|
||||
from: { data: 'tooltip' },
|
||||
encode: {
|
||||
update: {
|
||||
x: { scale: "xrelscale", field: "argmin.relTime" },
|
||||
y: { scale: "yscale", field: "argmin.y" },
|
||||
x: { scale: 'xrelscale', field: 'argmin.relTime' },
|
||||
y: { scale: 'yscale', field: 'argmin.y' },
|
||||
size: { value: 50 },
|
||||
fill: { value: "black" }
|
||||
fill: { value: 'black' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "group",
|
||||
from: { data: "tooltip" },
|
||||
type: 'group',
|
||||
from: { data: 'tooltip' },
|
||||
interactive: false,
|
||||
name: "tooltipGroup",
|
||||
name: 'tooltipGroup',
|
||||
encode: {
|
||||
update: {
|
||||
x: [
|
||||
{
|
||||
test:
|
||||
"inrange(datum.argmin.relTime + 80, domain('xrelscale'))",
|
||||
scale: "xrelscale",
|
||||
field: "argmin.relTime"
|
||||
scale: 'xrelscale',
|
||||
field: 'argmin.relTime'
|
||||
},
|
||||
{ scale: "xrelscale", field: "argmin.relTime", offset: -80 }
|
||||
{ scale: 'xrelscale', field: 'argmin.relTime', offset: -80 }
|
||||
],
|
||||
y: { scale: "yscale", field: "argmin.y" },
|
||||
y: { scale: 'yscale', field: 'argmin.y' },
|
||||
height: { value: 20 },
|
||||
width: { value: 80 },
|
||||
fill: { value: "#fff" },
|
||||
fill: { value: '#fff' },
|
||||
fillOpacity: { value: 0.85 },
|
||||
stroke: { value: "#aaa" },
|
||||
stroke: { value: '#aaa' },
|
||||
strokeWidth: { value: 0.5 }
|
||||
}
|
||||
},
|
||||
marks: [
|
||||
{
|
||||
type: "text",
|
||||
type: 'text',
|
||||
interactive: false,
|
||||
encode: {
|
||||
update: {
|
||||
|
@ -318,8 +318,8 @@ export default {
|
|||
signal:
|
||||
"format(parent.argmin.relTime, ',.2f') + ': ' + format(parent.argmin.y, ',.2f') + ' ' + parent.argmin.unit"
|
||||
},
|
||||
fill: { value: "black" },
|
||||
fontWeight: { value: "bold" },
|
||||
fill: { value: 'black' },
|
||||
fontWeight: { value: 'bold' },
|
||||
y: { value: 20 }
|
||||
}
|
||||
}
|
||||
|
@ -327,14 +327,14 @@ export default {
|
|||
]
|
||||
},
|
||||
{
|
||||
type: "rect",
|
||||
name: "boundingRect",
|
||||
type: 'rect',
|
||||
name: 'boundingRect',
|
||||
interactive: true,
|
||||
encode: {
|
||||
enter: {
|
||||
width: { signal: "width" },
|
||||
height: { signal: "height" },
|
||||
fill: { value: "transparent" }
|
||||
width: { signal: 'width' },
|
||||
height: { signal: 'height' },
|
||||
fill: { value: 'transparent' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-env worker */
|
||||
/* eslint-disable no-restricted-globals */
|
||||
import DBC from "../models/can/dbc";
|
||||
import DbcUtils from "../utils/dbc";
|
||||
import extend from "xtend";
|
||||
import extend from 'xtend';
|
||||
import DBC from '../models/can/dbc';
|
||||
import DbcUtils from '../utils/dbc';
|
||||
|
||||
function processStreamedCanMessages(
|
||||
newCanMessages,
|
||||
|
@ -21,17 +21,19 @@ function processStreamedCanMessages(
|
|||
canMessages = canMessages.sort((msg1, msg2) => {
|
||||
if (msg1[1] < msg2[1]) {
|
||||
return -1;
|
||||
} else if (msg1[1] > msg2[1]) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (msg1[1] > msg2[1]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
let busTimeSum = 0;
|
||||
|
||||
for (let i = 0; i < canMessages.length; i++) {
|
||||
let { address, busTime, data, bus } = canMessages[i];
|
||||
const {
|
||||
address, busTime, data, bus
|
||||
} = canMessages[i];
|
||||
|
||||
let prevBusTime;
|
||||
if (i === 0) {
|
||||
|
@ -78,7 +80,7 @@ function processStreamedCanMessages(
|
|||
maxByteStateChangeCount = newMaxByteStateChangeCount;
|
||||
}
|
||||
|
||||
Object.keys(messages).forEach(key => {
|
||||
Object.keys(messages).forEach((key) => {
|
||||
messages[key] = DbcUtils.setMessageByteColors(
|
||||
messages[key],
|
||||
maxByteStateChangeCount
|
||||
|
@ -95,7 +97,7 @@ function processStreamedCanMessages(
|
|||
});
|
||||
}
|
||||
|
||||
self.onmessage = function(e) {
|
||||
self.onmessage = function (e) {
|
||||
const {
|
||||
newCanMessages,
|
||||
prevMsgEntries,
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
/* eslint-disable no-restricted-globals */
|
||||
// import Sentry from '../logging/Sentry';
|
||||
|
||||
import NumpyLoader from "../utils/loadnpy";
|
||||
import NumpyLoader from '../utils/loadnpy';
|
||||
|
||||
const MAX_CONNECTIONS = 8;
|
||||
|
||||
var window = self;
|
||||
const window = self;
|
||||
|
||||
const Int64LE = require("int64-buffer").Int64LE;
|
||||
const { Int64LE } = require('int64-buffer');
|
||||
|
||||
function transformAndSend(rawData) {
|
||||
var totalSize = 0;
|
||||
var maxTime = rawData.reduce(function(memo, sourceData) {
|
||||
let totalSize = 0;
|
||||
const maxTime = rawData.reduce((memo, sourceData) => {
|
||||
totalSize += sourceData.entries.length;
|
||||
sourceData.entries = sourceData.entries.sort(function(a, b) {
|
||||
sourceData.entries = sourceData.entries.sort((a, b) => {
|
||||
if (a.relTime > b.relTime) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ function transformAndSend(rawData) {
|
|||
return Math.max(memo, getLastTimeFromEntries(sourceData.entries));
|
||||
}, 0);
|
||||
|
||||
var minTime = Math.max(0, maxTime - 30);
|
||||
console.log("Time span from", minTime, maxTime);
|
||||
var curIndexes = {};
|
||||
rawData.forEach(function(sourceData) {
|
||||
const minTime = Math.max(0, maxTime - 30);
|
||||
console.log('Time span from', minTime, maxTime);
|
||||
const curIndexes = {};
|
||||
rawData.forEach((sourceData) => {
|
||||
if (!sourceData.entries.length) {
|
||||
return;
|
||||
}
|
||||
var sourceId = sourceData.id;
|
||||
const sourceId = sourceData.id;
|
||||
if (minTime === 0 || sourceData.entries[0].relTime > minTime) {
|
||||
curIndexes[sourceId] = 0;
|
||||
return;
|
||||
|
@ -41,12 +41,12 @@ function transformAndSend(rawData) {
|
|||
curIndexes[sourceId] = findFirstEntryIndex(sourceData.entries, minTime);
|
||||
});
|
||||
|
||||
var entryBuffer = [];
|
||||
var totalEntries = 0;
|
||||
let entryBuffer = [];
|
||||
let totalEntries = 0;
|
||||
|
||||
while (!isAtEnd()) {
|
||||
let nextSource = rawData.reduce(function(memo, sourceData) {
|
||||
let curEntry = sourceData.entries[curIndexes[sourceData.id]];
|
||||
const nextSource = rawData.reduce((memo, sourceData) => {
|
||||
const curEntry = sourceData.entries[curIndexes[sourceData.id]];
|
||||
if (!curEntry) {
|
||||
return memo;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ function transformAndSend(rawData) {
|
|||
if (entryBuffer.length > 5000) {
|
||||
self.postMessage({
|
||||
progress: 100 * (totalEntries / totalSize),
|
||||
logData: entryBuffer.join("\n"),
|
||||
logData: entryBuffer.join('\n'),
|
||||
shouldClose: false
|
||||
});
|
||||
entryBuffer = [];
|
||||
|
@ -88,13 +88,13 @@ function transformAndSend(rawData) {
|
|||
if (entryBuffer.length > 0) {
|
||||
self.postMessage({
|
||||
progress: 99,
|
||||
logData: entryBuffer.join("\n"),
|
||||
logData: entryBuffer.join('\n'),
|
||||
shouldClose: false
|
||||
});
|
||||
entryBuffer = [];
|
||||
}
|
||||
|
||||
console.log("Wrote", totalEntries, "lines of CSV");
|
||||
console.log('Wrote', totalEntries, 'lines of CSV');
|
||||
self.postMessage({
|
||||
progress: 100,
|
||||
shouldClose: true
|
||||
|
@ -102,8 +102,7 @@ function transformAndSend(rawData) {
|
|||
|
||||
function isAtEnd() {
|
||||
return rawData.reduce(
|
||||
(memo, sourceData) =>
|
||||
memo && curIndexes[sourceData.id] >= sourceData.entries.length
|
||||
(memo, sourceData) => memo && curIndexes[sourceData.id] >= sourceData.entries.length
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +113,7 @@ function makeEntry(nextSource) {
|
|||
nextSource.address,
|
||||
nextSource.bus,
|
||||
nextSource.entry.hexData
|
||||
].join(",");
|
||||
].join(',');
|
||||
}
|
||||
|
||||
function findFirstEntryIndex(entries, minTime, start, length) {
|
||||
|
@ -160,11 +159,11 @@ function getLastTimeFromEntries(entries) {
|
|||
return entries[entries.length - 1].relTime;
|
||||
}
|
||||
|
||||
self.onmessage = function(e) {
|
||||
console.log("onmessage worker");
|
||||
self.onmessage = function (e) {
|
||||
console.log('onmessage worker');
|
||||
self.postMessage({
|
||||
progress: 0,
|
||||
logData: "time,addr,bus,data",
|
||||
logData: 'time,addr,bus,data',
|
||||
shouldClose: false
|
||||
});
|
||||
const {
|
||||
|
@ -180,7 +179,7 @@ self.onmessage = function(e) {
|
|||
// saveDBC(dbc, base, num, canStartTime);
|
||||
if (data) {
|
||||
// has raw data from live mode, process this instead
|
||||
console.log("Using raw data from memory", canStartTime);
|
||||
console.log('Using raw data from memory', canStartTime);
|
||||
transformAndSend(data, canStartTime);
|
||||
} else {
|
||||
self.postMessage({
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue