Skip to content

Commit

Permalink
Merge pull request #851 from stadtnavi/vehicle-positions
Browse files Browse the repository at this point in the history
Re-enable vehicle positions
  • Loading branch information
hbruch authored Dec 14, 2024
2 parents 227ba6a + 34b7478 commit d8579ce
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 56 deletions.
2 changes: 1 addition & 1 deletion app/component/DepartureListContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class DepartureListContainer extends Component {
.indexOf(departure.stop.code) >= 0,
)
.map(departure => ({
tripId: departure.trip.gtfsId.split(':')[1],
tripId: departure.trip.gtfsId.split(':').slice(1).join(':'),
}));

const { config } = this.context;
Expand Down
6 changes: 3 additions & 3 deletions app/component/ItineraryPageUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export function getTopics(config, itineraries, match) {
if (realTime[feedId]?.useFuzzyTripMatching) {
topic = {
feedId,
route: leg.route.gtfsId.split(':')[1],
route: leg.route.gtfsId.split(':').slice(1).join(':'),
mode: leg.mode.toLowerCase(),
direction: Number(leg.trip.directionId),
shortName: leg.route.shortName,
Expand All @@ -144,8 +144,8 @@ export function getTopics(config, itineraries, match) {
} else if (realTime[feedId]) {
topic = {
feedId,
route: leg.route.gtfsId.split(':')[1],
tripId: leg.trip.gtfsId.split(':')[1],
route: leg.route.gtfsId.split(':').slice(1).join(':'),
tripId: leg.trip.gtfsId.split(':').slice(1).join(':'),
type: leg.route.type,
shortName: leg.route.shortName,
};
Expand Down
6 changes: 3 additions & 3 deletions app/component/RoutePageControlPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class RoutePageControlPanel extends React.Component {
route: id,
feedId,
mode: route.mode.toLowerCase(),
gtfsId: routeParts[1],
gtfsId: routeParts.slice(1).join(':'),
headsign: pattern[0].headsign,
},
],
Expand Down Expand Up @@ -299,7 +299,7 @@ class RoutePageControlPanel extends React.Component {
const source = realTime[feedId];
const id =
pattern.code !== match.params.patternId
? routeParts[1]
? routeParts.slice(1).join(':')
: source.routeSelector(this.props);
if (!source || !source.active) {
return;
Expand All @@ -318,7 +318,7 @@ class RoutePageControlPanel extends React.Component {
// to compensate potentially missing feed data
feedId,
mode: route.mode.toLowerCase(),
gtfsId: routeParts[1],
gtfsId: routeParts.slice(1).join(':'),
headsign: pattern.headsign,
direction,
tripStartTime,
Expand Down
44 changes: 19 additions & 25 deletions app/component/RouteStopListContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,35 @@ import groupBy from 'lodash/groupBy';
import values from 'lodash/values';
import cx from 'classnames';
import { FormattedMessage } from 'react-intl';
import moment from 'moment-timezone';

import {
configShape,
relayShape,
vehicleShape,
patternShape,
} from '../util/shapes';
import RouteStop from './RouteStop';
import withBreakpoint from '../util/withBreakpoint';
import { getRouteMode } from '../util/modeUtils';
import { PatternShape, VehicleShape } from '../util/shapes';

class RouteStopListContainer extends React.PureComponent {
static propTypes = {
pattern: PatternShape.isRequired,
patternId: PropTypes.string.isRequired,
pattern: patternShape.isRequired,
className: PropTypes.string,
vehicles: PropTypes.objectOf(VehicleShape),
currentTime: PropTypes.instanceOf(moment).isRequired,
relay: PropTypes.shape({
refetch: PropTypes.func.isRequired,
}).isRequired,
vehicles: PropTypes.objectOf(vehicleShape),
currentTime: PropTypes.number.isRequired,
relay: relayShape.isRequired,
breakpoint: PropTypes.string.isRequired,
hideDepartures: PropTypes.bool,
};

static defaultProps = {
className: undefined,
vehicles: [],
hideDepartures: false,
};

static contextTypes = {
config: PropTypes.object.isRequired,
config: configShape.isRequired,
match: matchShape.isRequired,
};

Expand All @@ -44,20 +45,17 @@ class RouteStopListContainer extends React.PureComponent {
const mode = getRouteMode(this.props.pattern.route);
const vehicles = groupBy(
values(this.props.vehicles).filter(
vehicle =>
this.props.currentTime - vehicle.timestamp * 1000 < 5 * 60 * 1000,
vehicle => this.props.currentTime - vehicle.timestamp < 5 * 60,
),
vehicle => vehicle.next_stop,
);
const rowClassName = `bp-${this.props.breakpoint}`;

return stops.map((stop, i) => {
const idx = i; // DT-3159: using in key of RouteStop component
const idx = i;
const nextStop = stops[i + 1];
const prevStop = stops[i - 1];

const prevStopPattern =
i > 0 ? stops[i - 1].stopTimesForPattern[0] : null;
return (
<RouteStop
color={
Expand All @@ -71,18 +69,14 @@ class RouteStopListContainer extends React.PureComponent {
prevStop={prevStop}
mode={mode}
vehicle={vehicles[stop.gtfsId] ? vehicles[stop.gtfsId][0] : null}
currentTime={this.props.currentTime.unix()}
currentTime={this.props.currentTime}
last={i === stops.length - 1}
first={i === 0}
className={rowClassName}
displayNextDeparture={this.context.config.displayNextDeparture}
shortName={
this.props.pattern.route && this.props.pattern.route.shortName
}
prevVehicleDeparture={
prevStopPattern ? prevStopPattern.scheduledDeparture : null
}
patternId={this.props.patternId.split('-')[1]}
hideDepartures={this.props.hideDepartures}
/>
);
Expand All @@ -91,12 +85,12 @@ class RouteStopListContainer extends React.PureComponent {

// eslint-disable-next-line camelcase
UNSAFE_componentWillReceiveProps({ relay, currentTime }) {
const currUnix = this.props.currentTime.unix();
const nextUnix = currentTime.unix();
if (currUnix !== nextUnix) {
const curr = this.props.currentTime;
const next = currentTime;
if (curr !== next) {
relay.refetch(
{
currentTime: nextUnix,
currentTime: next,
patternId: this.context.match.params.patternId,
},
null,
Expand Down
6 changes: 3 additions & 3 deletions app/component/map/StopsNearYouMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,10 @@ function StopsNearYouMap(
// eslint-disable-next-line no-unused-expressions
place.patterns &&
place.patterns.forEach(pattern => {
const feedId = pattern.route.gtfsId.split(':')[0];
const feedId = pattern.route.gtfsId.split(':').slice(1).join(':');
realtimeTopics.push({
feedId,
route: pattern.route.gtfsId.split(':')[1],
route: pattern.route.gtfsId.split(':').slice(1).join(':'),
shortName: pattern.route.shortName,
type: pattern.route.type,
});
Expand All @@ -293,7 +293,7 @@ function StopsNearYouMap(
const feedId = pattern.route.gtfsId.split(':')[0];
realtimeTopics.push({
feedId,
route: pattern.route.gtfsId.split(':')[1],
route: pattern.route.gtfsId.split(':').slice(1).join(':'),
shortName: pattern.route.shortName,
type: pattern.route.type,
});
Expand Down
4 changes: 3 additions & 1 deletion app/component/map/VehicleMarkerContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ function VehicleMarkerContainer(props) {
icon={getVehicleIcon(
mode,
message.heading,
message.shortName ? message.shortName : message.route.split(':')[1],
message.shortName
? message.shortName
: message.route.split(':').slice(1).join(':'),
message.color,
props.useLargeIcon,
)}
Expand Down
5 changes: 0 additions & 5 deletions app/configurations/config.herrenberg.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ const STATIC_MESSAGE_URL =

const parentConfig = require('./config.stadtnavi.js').default;

const realtimeHbg = require('./realtimeUtils').default.hbg;
const hostname = new URL(API_URL);
realtimeHbg.mqtt = `wss://${hostname.host}/mqtt/`;

const minLat = 47.6020;
const maxLat = 49.0050;
const minLon = 8.4087;
Expand Down Expand Up @@ -234,8 +231,6 @@ export default configMerger(parentConfig, {

feedIds: ['hbg'],

realtime: { hbg: realtimeHbg },

searchSources: ['oa', 'osm'],

searchParams: {
Expand Down
39 changes: 35 additions & 4 deletions app/configurations/realtimeUtils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable prefer-template */
function defaultRouteSelector(routePageProps) {
const route = routePageProps.route.gtfsId.split(':');
return route[1];
return route.slice(1).join(':');
}
function walttiTopicResolver(
route,
Expand Down Expand Up @@ -286,12 +286,43 @@ export default {
active: true,
},
hbg: {
mqttTopicResolver: function mqttTopicResolver() {
return '/gtfsrt/vp/#';
mqttTopicResolver: function hbgTopicResolver(
route,
direction,
tripStartTime,
headsign,
feedId,
tripId,
geoHash,
) {
return (
'/gtfsrt/vp/' +
feedId +
'/+/+/+/' +
route +
'/' +
'+' + // direction is not available in VVS GTFS-RT-VP feed
'/' +
'+' + // headsign is not available in VVS GTFS-RT-VP feed
'/' +
tripId +
'/+/' +
'+' + // tripstartTime is not available in VVS GTFS-RT-VP feed
'/+/' +
geoHash[0] +
'/' +
geoHash[1] +
'/' +
geoHash[2] +
'/' +
geoHash[3] +
'/#'
);
},

// this value is overridden in config.herrenberg.js
mqtt: 'wss://api.dev.stadtnavi.eu/mqtt/',
mqtt: 'wss://vehiclepositions.stadtnavi.eu/mqtt/',
topicFeedId: 'hbg',

gtfsrt: true,

Expand Down
8 changes: 4 additions & 4 deletions app/store/RealTimeInformationStore.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Store from 'fluxible/addons/BaseStore';
import moment from 'moment';
import events from '../util/events';
import { unixTime } from '../util/timeUtils';

class RealTimeInformationStore extends Store {
static storeName = 'RealTimeInformationStore';
Expand Down Expand Up @@ -61,20 +61,20 @@ class RealTimeInformationStore extends Store {

handleMessage(message) {
if (message) {
const receivedAt = moment().unix();
const receivedAt = unixTime();
if (Array.isArray(message)) {
message.forEach(msg => {
if (
!this.topicsByRoute ||
this.topicsByRoute[msg.route.split(':')[1]]
this.topicsByRoute[msg.route.split(':').slice(1).join(':')]
) {
// Filter out old messages
this.vehicles[msg.id] = { ...msg, receivedAt };
}
});
} else if (
!this.topicsByRoute ||
this.topicsByRoute[message.route.split(':')[1]]
this.topicsByRoute[message.route.split(':').slice(1).join(':')]
) {
this.vehicles[message.id] = { ...message, receivedAt };
}
Expand Down
6 changes: 3 additions & 3 deletions app/util/gtfsRtParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const parseFeedMQTT = (feedParser, data, topic, agency) => {
,
,
,
,
feedId,
,
,
mode,
Expand All @@ -55,8 +55,8 @@ export const parseFeedMQTT = (feedParser, data, topic, agency) => {
const { trip, position, vehicle } = vehiclePos;
if (trip && position && vehicle) {
const message = {
id: `${agency}:${vehicleId}`,
route: `${agency}:${routeId}`,
id: `${feedId}:${vehicleId}`,
route: `${feedId}:${routeId}`,
direction:
directionId === '' ? undefined : parseInt(directionId, 10) || 0,
tripStartTime:
Expand Down
2 changes: 1 addition & 1 deletion app/util/mqttClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export function startMqttClient(settings, actionContext) {
topic,
settings.agency,
);
parsedMessages.forEach(message => {
parsedMessages?.forEach(message => {
actionContext.dispatch('RealTimeClientMessage', message);
});
});
Expand Down
6 changes: 3 additions & 3 deletions test/unit/component/RouteStopListContainer.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React from 'react';
import moment from 'moment-timezone';

import { shallowWithIntl } from '../helpers/mock-intl-enzyme';
import { Component as RouteStopListContainer } from '../../../app/component/RouteStopListContainer';
import { mockMatch } from '../helpers/mock-router';

describe('<RouteStopListContainer />', () => {
it('should render route stop list', () => {
const props = {
currentTime: moment(1573135114),
currentTime: 1573135114,
pattern: {
directionId: 0,
code: 'feed:1',
Expand Down Expand Up @@ -102,11 +100,13 @@ describe('<RouteStopListContainer />', () => {
breakpoint: 'large',
relay: {
refetch: () => {},
environment: {},
},
};
const wrapper = shallowWithIntl(<RouteStopListContainer {...props} />, {
context: {
config: {
CONFIG: 'default',
nearestStopDistance: {},
},
match: mockMatch,
Expand Down

0 comments on commit d8579ce

Please sign in to comment.