diff --git a/webapp/src/app/sfera-observer/sfera-observer.component.html b/webapp/src/app/sfera-observer/sfera-observer.component.html
index e5e15944..57b771cf 100644
--- a/webapp/src/app/sfera-observer/sfera-observer.component.html
+++ b/webapp/src/app/sfera-observer/sfera-observer.component.html
@@ -32,6 +32,7 @@
SFERA Communication
+
@if (environmentControl.value) {
diff --git a/webapp/src/app/sfera-observer/sfera-observer.component.ts b/webapp/src/app/sfera-observer/sfera-observer.component.ts
index 61db2049..a09b9259 100644
--- a/webapp/src/app/sfera-observer/sfera-observer.component.ts
+++ b/webapp/src/app/sfera-observer/sfera-observer.component.ts
@@ -12,7 +12,12 @@ import { SbbCheckboxModule } from "@sbb-esta/angular/checkbox";
import { environment } from "../../environment/environment";
import { MessageTableComponent, TableData } from "./message-table/message-table.component";
import { SbbTableDataSource } from "@sbb-esta/angular/table";
-import { READONLY_MODE, SferaXmlCreation, SpRequestOptions } from "./sfera-xml-creation";
+import {
+ READONLY_MODE,
+ SferaXmlCreation,
+ SpRequestOptions,
+ TcRequestOptions
+} from "./sfera-xml-creation";
import { SbbAccordionModule } from "@sbb-esta/angular/accordion";
@Component({
@@ -134,6 +139,8 @@ export class SferaObserverComponent implements OnDestroy {
return `JP: ${this.getJourneyProfileStatus(document)}, #SP: ${this.getJourneyProfileNumberOfSPs(document)}`;
} else if (this.containsElement(document, 'SegmentProfile')) {
return this.getSegmentProfiles(document);
+ } else if(this.containsElement(document, 'TrainCharacteristics')) {
+ return this.getTrainCharacteristics(document);
}
} else if (type == "SFERA_B2G_RequestMessage") {
if (this.isHandshakeRequest(document)) {
@@ -205,7 +212,12 @@ export class SferaObserverComponent implements OnDestroy {
private getSegmentProfiles(document: Document) {
const segmentProfiles = Array.from(document.getElementsByTagName("SegmentProfile"));
- return segmentProfiles.map(segmentProfile => `SP ${this.getSegmentProfileId(segmentProfile)}: ${this.getSegmentProfileStatus(segmentProfile)}, Length: ${this.getSegmentProfileLength(segmentProfile)}`).join('\n')
+ return segmentProfiles.map(segmentProfile => `SP ${this.getSegmentProfileId(segmentProfile)}: ${this.getSegmentProfileStatus(segmentProfile)}, Length: ${this.getSegmentProfileLength(segmentProfile)}`).join(', ')
+ }
+
+ private getTrainCharacteristics(document: Document) {
+ const trainCharacteristics = Array.from(document.getElementsByTagName("TrainCharacteristics"));
+ return trainCharacteristics.map(trainCharacteristic => `TC ${this.getTrainCharacteristicsId(trainCharacteristic)}`).join(', ');
}
private getSegmentProfileStatus(element: Element) {
@@ -220,6 +232,10 @@ export class SferaObserverComponent implements OnDestroy {
return element.getAttribute("SP_ID");
}
+ private getTrainCharacteristicsId(element: Element) {
+ return element.getAttribute("TC_ID");
+ }
+
sendXml() {
const xmlString = this.xmlStringControl.value;
this.mqService.publish(this.b2gTopic!, xmlString);
@@ -286,6 +302,40 @@ export class SferaObserverComponent implements OnDestroy {
this.mqService.publish(this.b2gTopic!, spRequest);
}
+ sendTCRequest() {
+ const jpReplies = this.data.filter(row => row.type === 'SFERA_G2B_ReplyMessage' && row.info.includes('JP: Valid'))
+ if (jpReplies.length === 0) {
+ alert('No JP request sent')
+ return;
+ }
+
+ const dom = this.toDom(jpReplies[jpReplies.length - 1].message)
+
+ const trainCharacteristicsRefs = Array.from(dom.getElementsByTagName('TrainCharacteristicsRef'));
+
+ const trainCharacteristics = trainCharacteristicsRefs.map(element => {
+ const tcId = element.getAttribute('TC_ID');
+ const ruId = element.getElementsByTagName('TC_RU_ID')[0].textContent;
+ const minorVersion = element.getAttribute('TC_VersionMajor');
+ const majorVersion = element.getAttribute('TC_VersionMinor');
+
+ return {
+ ruId: ruId,
+ tcId: tcId,
+ majorVersion: majorVersion,
+ minorVersion: minorVersion
+ } as TcRequestOptions;
+ });
+
+ const tcRequest = SferaXmlCreation.createRequest({
+ header: {
+ sourceDevice: this.clientIdControl.value
+ },
+ tcRequests: trainCharacteristics
+ });
+ this.mqService.publish(this.b2gTopic!, tcRequest);
+ }
+
sendHSRWrongSferaVersion() {
const handshakeRequest = SferaXmlCreation.createHandshakeRequest({
header: {
diff --git a/webapp/src/app/sfera-observer/sfera-xml-creation.ts b/webapp/src/app/sfera-observer/sfera-xml-creation.ts
index c6407392..303e0641 100644
--- a/webapp/src/app/sfera-observer/sfera-xml-creation.ts
+++ b/webapp/src/app/sfera-observer/sfera-xml-creation.ts
@@ -43,10 +43,18 @@ export interface SpRequestOptions {
minorVersion: string;
}
+export interface TcRequestOptions {
+ ruId: string;
+ tcId: string;
+ majorVersion: string;
+ minorVersion: string;
+}
+
export interface RequestOptions {
header?: SferaHeaderOptions,
- jpRequests?: JpRequestOptions[]
- spRequests?: SpRequestOptions[]
+ jpRequests?: JpRequestOptions[],
+ spRequests?: SpRequestOptions[],
+ tcRequests?: TcRequestOptions[]
}
export interface SupportedOperationModes {
@@ -106,6 +114,7 @@ export class SferaXmlCreation {
const jpRequests = this.createJpRequest(options.jpRequests);
const spRequests = this.createSpRequest(options.spRequests);
+ const tcRequests = this.createTcRequest(options.tcRequests);
return `
@@ -116,6 +125,7 @@ export class SferaXmlCreation {
${jpRequests}
${spRequests}
+ ${tcRequests}
`;
@@ -167,6 +177,16 @@ export class SferaXmlCreation {
return (strings || []).join('');
}
+ static createTcRequest(tcRequests: TcRequestOptions[] | undefined): string {
+ const strings = tcRequests?.map(tcRequest => {
+ return `
+ ${tcRequest.ruId}
+
+ `;
+ })
+ return (strings || []).join('');
+ }
+
private static defaultHeader(): SferaHeaderOptions {
return {
sferaVersion: '2.01',