diff --git a/src/components/draw-app/DrawRelayCabinetProperties.vue b/src/components/draw-app/DrawRelayCabinetProperties.vue
index 678f791..8316497 100644
--- a/src/components/draw-app/DrawRelayCabinetProperties.vue
+++ b/src/components/draw-app/DrawRelayCabinetProperties.vue
@@ -27,6 +27,11 @@
PhaseFailureProtector.Type
"
>
+
@@ -41,6 +46,8 @@ import RelayProperty from './properties/RelayProperty.vue';
import { Relay } from 'src/graphics/relay/Relay';
import PhaseFailureProtectorProperty from './properties/PhaseFailureProtectorProperty.vue';
import { PhaseFailureProtector } from 'src/graphics/phaseFailureProtector/PhaseFailureProtector';
+import SignalFaultAlarmProperty from './properties/SignalFaultAlarmProperty.vue';
+import { SignalFaultAlarm } from 'src/graphics/signalFaultAlarm/SignalFaultAlarm';
import { useRelayCabinetStore } from 'src/stores/relayCabinet-store';
const relayCabinetStore = useRelayCabinetStore();
diff --git a/src/components/draw-app/dialogs/DeviceRelateRelayList.vue b/src/components/draw-app/dialogs/DeviceRelateRelayList.vue
index f5ccdc2..c6d787b 100644
--- a/src/components/draw-app/dialogs/DeviceRelateRelayList.vue
+++ b/src/components/draw-app/dialogs/DeviceRelateRelayList.vue
@@ -63,6 +63,7 @@ const deviceTypeMap = {
5: '信号机',
6: '车站',
7: '屏蔽门',
+ 8: '信号机故障报警仪',
};
const columns: QTable['columns'] = [
{
diff --git a/src/components/draw-app/properties/RelateRelayConfig.vue b/src/components/draw-app/properties/RelateRelayConfig.vue
index a1ac778..d43992b 100644
--- a/src/components/draw-app/properties/RelateRelayConfig.vue
+++ b/src/components/draw-app/properties/RelateRelayConfig.vue
@@ -133,6 +133,10 @@ const optionsType = [
{ label: '信号机', value: graphicData.RelatedRef.DeviceType.signal },
{ label: '车站', value: graphicData.RelatedRef.DeviceType.station },
{ label: '屏蔽门', value: graphicData.RelatedRef.DeviceType.ScreenDoor },
+ {
+ label: '信号机故障报警仪',
+ value: graphicData.RelatedRef.DeviceType.SignalFaultAlarm,
+ },
];
let selectGraphic: JlGraphic[] = [];
diff --git a/src/components/draw-app/properties/SignalFaultAlarmProperty.vue b/src/components/draw-app/properties/SignalFaultAlarmProperty.vue
new file mode 100644
index 0000000..c152078
--- /dev/null
+++ b/src/components/draw-app/properties/SignalFaultAlarmProperty.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
diff --git a/src/drawApp/relayCabinetGraphics/SignalFaultAlarmInteraction.ts b/src/drawApp/relayCabinetGraphics/SignalFaultAlarmInteraction.ts
new file mode 100644
index 0000000..2878442
--- /dev/null
+++ b/src/drawApp/relayCabinetGraphics/SignalFaultAlarmInteraction.ts
@@ -0,0 +1,46 @@
+import * as pb_1 from 'google-protobuf';
+import {
+ ISignalFaultAlarmData,
+ SignalFaultAlarm,
+} from 'src/graphics/signalFaultAlarm/SignalFaultAlarm';
+import { relayCabinetGraphicData } from 'src/protos/relayCabinetLayoutGraphics';
+import { GraphicDataBase } from '../graphics/GraphicDataBase';
+
+export class SignalFaultAlarmData
+ extends GraphicDataBase
+ implements ISignalFaultAlarmData
+{
+ constructor(data?: relayCabinetGraphicData.SignalFaultAlarm) {
+ let signalFaultAlarm;
+ if (!data) {
+ signalFaultAlarm = new relayCabinetGraphicData.SignalFaultAlarm(
+ {
+ common: GraphicDataBase.defaultCommonInfo(SignalFaultAlarm.Type),
+ }
+ );
+ } else {
+ signalFaultAlarm = data;
+ }
+ super(signalFaultAlarm);
+ }
+
+ public get data(): relayCabinetGraphicData.SignalFaultAlarm {
+ return this.getData();
+ }
+
+ get code(): string {
+ return this.data.code;
+ }
+ set code(v: string) {
+ this.data.code = v;
+ }
+ clone(): SignalFaultAlarmData {
+ return new SignalFaultAlarmData(this.data.cloneMessage());
+ }
+ copyFrom(data: SignalFaultAlarmData): void {
+ pb_1.Message.copyInto(data.data, this.data);
+ }
+ eq(other: SignalFaultAlarmData): boolean {
+ return pb_1.Message.equals(this.data, other.data);
+ }
+}
diff --git a/src/drawApp/relayCabinetLayoutApp.ts b/src/drawApp/relayCabinetLayoutApp.ts
index d423185..4a9bd00 100644
--- a/src/drawApp/relayCabinetLayoutApp.ts
+++ b/src/drawApp/relayCabinetLayoutApp.ts
@@ -33,6 +33,12 @@ import {
} from 'src/graphics/phaseFailureProtector/PhaseFailureProtector';
import { PhaseFailureProtectorData } from './relayCabinetGraphics/PhaseFailureProtectorInteraction';
import { PhaseFailureProtectorDraw } from 'src/graphics/phaseFailureProtector/PhaseFailureProtectorDrawAssistant';
+import {
+ SignalFaultAlarm,
+ SignalFaultAlarmTemplate,
+} from 'src/graphics/signalFaultAlarm/SignalFaultAlarm';
+import { SignalFaultAlarmData } from './relayCabinetGraphics/SignalFaultAlarmInteraction';
+import { SignalFaultAlarmDraw } from 'src/graphics/signalFaultAlarm/SignalFaultAlarmDrawAssistant';
const UndoOptions: MenuItemOptions = {
name: '撤销',
@@ -80,6 +86,10 @@ export function initDrawApp(): IDrawApp {
app,
new PhaseFailureProtectorTemplate(new PhaseFailureProtectorData())
);
+ new SignalFaultAlarmDraw(
+ app,
+ new SignalFaultAlarmTemplate(new SignalFaultAlarmData())
+ );
// 画布右键菜单
app.registerMenu(DefaultCanvasMenu);
@@ -205,6 +215,12 @@ export function saveDrawDatas(app: IDrawApp) {
(phaseFailureProtectorData as PhaseFailureProtectorData).data
);
}
+ if (SignalFaultAlarm.Type === g.type) {
+ const signalFaultAlarmData = (g as SignalFaultAlarm).saveData();
+ storage.signalFaultAlarms.push(
+ (signalFaultAlarmData as SignalFaultAlarmData).data
+ );
+ }
});
storage.deviceRelateRelayList = refRelaysList;
storage.combinationtypeList = combinationTypeList;
@@ -236,6 +252,9 @@ export async function loadDrawDatas(): Promise {
storage.phaseFailureProtectors.forEach((phaseFailureProtector) => {
datas.push(new PhaseFailureProtectorData(phaseFailureProtector));
});
+ storage.signalFaultAlarms.forEach((signalFaultAlarm) => {
+ datas.push(new SignalFaultAlarmData(signalFaultAlarm));
+ });
refRelaysList = storage.deviceRelateRelayList;
combinationTypeList = storage.combinationtypeList;
UniqueIdPrefix = storage.UniqueIdPrefix;
diff --git a/src/graphics/signalFaultAlarm/SignalFaultAlarm.ts b/src/graphics/signalFaultAlarm/SignalFaultAlarm.ts
new file mode 100644
index 0000000..239c8d7
--- /dev/null
+++ b/src/graphics/signalFaultAlarm/SignalFaultAlarm.ts
@@ -0,0 +1,80 @@
+import { Assets, Sprite, Texture } from 'pixi.js';
+import {
+ GraphicData,
+ JlGraphic,
+ JlGraphicTemplate,
+ VectorText,
+} from 'src/jl-graphic';
+import signalFaultAlarmSprites from './signalFaultAlarmSprites.png';
+
+export interface ISignalFaultAlarmData extends GraphicData {
+ get code(): string; // 编号
+ set code(v: string);
+ clone(): ISignalFaultAlarmData;
+ copyFrom(data: ISignalFaultAlarmData): void;
+ eq(other: ISignalFaultAlarmData): boolean;
+}
+
+export const signalFaultAlarmConsts = {
+ scaleX: 0.2,
+ scaleY: 0.2,
+};
+export class SignalFaultAlarm extends JlGraphic {
+ static Type = 'SignalFaultAlarm';
+ signalFaultAlarm: Sprite;
+ signalFaultAlarmTextures: Texture;
+ labelGraphic = new VectorText();
+
+ constructor(signalFaultAlarmTextures: Texture) {
+ super(SignalFaultAlarm.Type);
+ this.signalFaultAlarmTextures = signalFaultAlarmTextures;
+ this.signalFaultAlarm = new Sprite();
+ this.signalFaultAlarm.texture = this.signalFaultAlarmTextures;
+ this.signalFaultAlarm.anchor.set(0.5, 0.5);
+ this.signalFaultAlarm.scale.set(
+ signalFaultAlarmConsts.scaleX,
+ signalFaultAlarmConsts.scaleY
+ );
+ this.addChild(this.signalFaultAlarm);
+ this.setTextGraphic(this.labelGraphic, 'label');
+ this.addChild(this.labelGraphic);
+ }
+
+ get datas(): ISignalFaultAlarmData {
+ return this.getDatas();
+ }
+ doRepaint(): void {
+ this.labelGraphic.text = this.datas.code;
+ this.labelGraphic.position.set(0, 25);
+ }
+ setTextGraphic(g: VectorText, name: string) {
+ g.setVectorFontSize(10);
+ g.anchor.set(0.5);
+ g.style.fill = '#0f0';
+ g.transformSave = true;
+ g.name = name;
+ }
+}
+
+export class SignalFaultAlarmTemplate extends JlGraphicTemplate {
+ signalFaultAlarmTextures?: Texture;
+ constructor(dataTemplate: ISignalFaultAlarmData) {
+ super(SignalFaultAlarm.Type, {
+ dataTemplate,
+ });
+ }
+ new(): SignalFaultAlarm {
+ if (this.signalFaultAlarmTextures) {
+ const signalFaultAlarm = new SignalFaultAlarm(
+ this.signalFaultAlarmTextures
+ );
+ signalFaultAlarm.loadData(this.datas);
+ return signalFaultAlarm;
+ }
+ throw new Error('资源未加载/加载失败');
+ }
+ async loadAssets(): Promise {
+ this.signalFaultAlarmTextures = await Assets.load(signalFaultAlarmSprites);
+ return this.signalFaultAlarmTextures as Texture;
+ }
+}
diff --git a/src/graphics/signalFaultAlarm/SignalFaultAlarmDrawAssistant.ts b/src/graphics/signalFaultAlarm/SignalFaultAlarmDrawAssistant.ts
new file mode 100644
index 0000000..9bcd783
--- /dev/null
+++ b/src/graphics/signalFaultAlarm/SignalFaultAlarmDrawAssistant.ts
@@ -0,0 +1,104 @@
+import { FederatedPointerEvent, Point } from 'pixi.js';
+import {
+ AbsorbableLine,
+ AbsorbablePosition,
+ GraphicDrawAssistant,
+ GraphicInteractionPlugin,
+ IDrawApp,
+ JlGraphic,
+} from 'src/jl-graphic';
+
+import {
+ ISignalFaultAlarmData,
+ SignalFaultAlarm,
+ SignalFaultAlarmTemplate,
+} from './SignalFaultAlarm';
+import { Relay } from '../relay/Relay';
+
+export interface ISignalFaultAlarmDrawOptions {
+ newData: () => ISignalFaultAlarmData;
+}
+
+export class SignalFaultAlarmDraw extends GraphicDrawAssistant<
+ SignalFaultAlarmTemplate,
+ ISignalFaultAlarmData
+> {
+ signalFaultAlarmGraphic: SignalFaultAlarm | null = null;
+
+ constructor(app: IDrawApp, template: SignalFaultAlarmTemplate) {
+ super(app, template, 'notifications_active', '信号机故障报警仪');
+ signalFaultAlarmInteraction.init(app);
+ }
+ bind(): void {
+ super.bind();
+ if (!this.signalFaultAlarmGraphic) {
+ this.signalFaultAlarmGraphic = this.graphicTemplate.new();
+ this.container.addChild(this.signalFaultAlarmGraphic);
+ }
+ }
+
+ onLeftDown(e: FederatedPointerEvent): void {
+ this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
+ this.createAndStore(true);
+ }
+
+ redraw(p: Point): void {
+ this.container.position.copyFrom(p);
+ }
+ prepareData(data: ISignalFaultAlarmData): boolean {
+ data.transform = this.container.saveTransform();
+ return true;
+ }
+}
+
+/**
+ * 构建吸附位置
+ * @param polygon
+ * @returns
+ */
+function buildAbsorbablePositions(
+ signalFaultAlarmCabinet: SignalFaultAlarm
+): AbsorbablePosition[] {
+ const aps: AbsorbablePosition[] = [];
+ const relays = signalFaultAlarmCabinet.queryStore.queryByType(
+ Relay.Type
+ );
+ const { width, height } = signalFaultAlarmCabinet.getGraphicApp().canvas;
+ relays.forEach((relay) => {
+ const ps = relay.position;
+ const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y });
+ const ys = new AbsorbableLine({ x: ps.x, y: 0 }, { x: ps.x, y: height });
+ aps.push(xs, ys);
+ });
+ return aps;
+}
+
+export class signalFaultAlarmInteraction extends GraphicInteractionPlugin {
+ static Name = 'signalFaultAlarm_transform';
+ constructor(app: IDrawApp) {
+ super(signalFaultAlarmInteraction.Name, app);
+ }
+ static init(app: IDrawApp) {
+ return new signalFaultAlarmInteraction(app);
+ }
+ filter(...grahpics: JlGraphic[]): SignalFaultAlarm[] | undefined {
+ return grahpics
+ .filter((g) => g.type === SignalFaultAlarm.Type)
+ .map((g) => g as SignalFaultAlarm);
+ }
+ bind(g: SignalFaultAlarm): void {
+ g.eventMode = 'static';
+ g.cursor = 'pointer';
+ g.on('transformstart', this.move, this);
+ }
+ unbind(g: SignalFaultAlarm): void {
+ g.eventMode = 'none';
+ g.off('transformstart', this.move, this);
+ }
+ move(): void {
+ const signalFaultAlarm = this.app.selectedGraphics[0] as SignalFaultAlarm;
+ this.app.setOptions({
+ absorbablePositions: buildAbsorbablePositions(signalFaultAlarm),
+ });
+ }
+}
diff --git a/src/graphics/signalFaultAlarm/signalFaultAlarmSprites.png b/src/graphics/signalFaultAlarm/signalFaultAlarmSprites.png
new file mode 100644
index 0000000..dd8830e
Binary files /dev/null and b/src/graphics/signalFaultAlarm/signalFaultAlarmSprites.png differ
diff --git a/src/layouts/RelayCabinetLayout.vue b/src/layouts/RelayCabinetLayout.vue
index fb0da20..507b222 100644
--- a/src/layouts/RelayCabinetLayout.vue
+++ b/src/layouts/RelayCabinetLayout.vue
@@ -198,6 +198,7 @@ import { DialogChainObject, useQuasar } from 'quasar';
import { Relay } from 'src/graphics/relay/Relay';
import { RelayCabinet } from 'src/graphics/relayCabinet/RelayCabinet';
import { PhaseFailureProtector } from 'src/graphics/phaseFailureProtector/PhaseFailureProtector';
+import { SignalFaultAlarm } from 'src/graphics/signalFaultAlarm/SignalFaultAlarm';
import { relayCabinetGraphicData } from 'src/protos/relayCabinetLayoutGraphics';
const $q = useQuasar();
@@ -291,6 +292,7 @@ onMounted(() => {
RelayCabinet.Type,
Relay.Type,
PhaseFailureProtector.Type,
+ SignalFaultAlarm.Type,
];
drawAssistantsTypes.forEach((type) => {
const drawAssistant = getDrawApp()?.getDrawAssistant(type);
diff --git a/src/protos/relayCabinetLayoutGraphics.ts b/src/protos/relayCabinetLayoutGraphics.ts
index b7b845f..5cd96d9 100644
--- a/src/protos/relayCabinetLayoutGraphics.ts
+++ b/src/protos/relayCabinetLayoutGraphics.ts
@@ -16,9 +16,10 @@ export namespace relayCabinetGraphicData {
UniqueIdPrefix?: UniqueIdType;
phaseFailureProtectors?: PhaseFailureProtector[];
combinationtypeList?: Combinationtype[];
+ signalFaultAlarms?: SignalFaultAlarm[];
}) {
super();
- pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 7, 8], this.#one_of_decls);
+ pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 7, 8, 9], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("canvas" in data && data.canvas != undefined) {
this.canvas = data.canvas;
@@ -41,6 +42,9 @@ export namespace relayCabinetGraphicData {
if ("combinationtypeList" in data && data.combinationtypeList != undefined) {
this.combinationtypeList = data.combinationtypeList;
}
+ if ("signalFaultAlarms" in data && data.signalFaultAlarms != undefined) {
+ this.signalFaultAlarms = data.signalFaultAlarms;
+ }
}
}
get canvas() {
@@ -91,6 +95,12 @@ export namespace relayCabinetGraphicData {
set combinationtypeList(value: Combinationtype[]) {
pb_1.Message.setRepeatedWrapperField(this, 8, value);
}
+ get signalFaultAlarms() {
+ return pb_1.Message.getRepeatedWrapperField(this, SignalFaultAlarm, 9) as SignalFaultAlarm[];
+ }
+ set signalFaultAlarms(value: SignalFaultAlarm[]) {
+ pb_1.Message.setRepeatedWrapperField(this, 9, value);
+ }
static fromObject(data: {
canvas?: ReturnType;
relayCabinets?: ReturnType[];
@@ -99,6 +109,7 @@ export namespace relayCabinetGraphicData {
UniqueIdPrefix?: ReturnType;
phaseFailureProtectors?: ReturnType[];
combinationtypeList?: ReturnType[];
+ signalFaultAlarms?: ReturnType[];
}): RelayCabinetGraphicStorage {
const message = new RelayCabinetGraphicStorage({});
if (data.canvas != null) {
@@ -122,6 +133,9 @@ export namespace relayCabinetGraphicData {
if (data.combinationtypeList != null) {
message.combinationtypeList = data.combinationtypeList.map(item => Combinationtype.fromObject(item));
}
+ if (data.signalFaultAlarms != null) {
+ message.signalFaultAlarms = data.signalFaultAlarms.map(item => SignalFaultAlarm.fromObject(item));
+ }
return message;
}
toObject() {
@@ -133,6 +147,7 @@ export namespace relayCabinetGraphicData {
UniqueIdPrefix?: ReturnType;
phaseFailureProtectors?: ReturnType[];
combinationtypeList?: ReturnType[];
+ signalFaultAlarms?: ReturnType[];
} = {};
if (this.canvas != null) {
data.canvas = this.canvas.toObject();
@@ -155,6 +170,9 @@ export namespace relayCabinetGraphicData {
if (this.combinationtypeList != null) {
data.combinationtypeList = this.combinationtypeList.map((item: Combinationtype) => item.toObject());
}
+ if (this.signalFaultAlarms != null) {
+ data.signalFaultAlarms = this.signalFaultAlarms.map((item: SignalFaultAlarm) => item.toObject());
+ }
return data;
}
serialize(): Uint8Array;
@@ -175,6 +193,8 @@ export namespace relayCabinetGraphicData {
writer.writeRepeatedMessage(7, this.phaseFailureProtectors, (item: PhaseFailureProtector) => item.serialize(writer));
if (this.combinationtypeList.length)
writer.writeRepeatedMessage(8, this.combinationtypeList, (item: Combinationtype) => item.serialize(writer));
+ if (this.signalFaultAlarms.length)
+ writer.writeRepeatedMessage(9, this.signalFaultAlarms, (item: SignalFaultAlarm) => item.serialize(writer));
if (!w)
return writer.getResultBuffer();
}
@@ -205,6 +225,9 @@ export namespace relayCabinetGraphicData {
case 8:
reader.readMessage(message.combinationtypeList, () => pb_1.Message.addToRepeatedWrapperField(message, 8, Combinationtype.deserialize(reader), Combinationtype));
break;
+ case 9:
+ reader.readMessage(message.signalFaultAlarms, () => pb_1.Message.addToRepeatedWrapperField(message, 9, SignalFaultAlarm.deserialize(reader), SignalFaultAlarm));
+ break;
default: reader.skipField();
}
}
@@ -532,6 +555,99 @@ export namespace relayCabinetGraphicData {
return PhaseFailureProtector.deserialize(bytes);
}
}
+ export class SignalFaultAlarm extends pb_1.Message {
+ #one_of_decls: number[][] = [];
+ constructor(data?: any[] | {
+ common?: dependency_1.graphicData.CommonInfo;
+ code?: string;
+ }) {
+ super();
+ pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
+ if (!Array.isArray(data) && typeof data == "object") {
+ if ("common" in data && data.common != undefined) {
+ this.common = data.common;
+ }
+ if ("code" in data && data.code != undefined) {
+ this.code = data.code;
+ }
+ }
+ }
+ get common() {
+ return pb_1.Message.getWrapperField(this, dependency_1.graphicData.CommonInfo, 1) as dependency_1.graphicData.CommonInfo;
+ }
+ set common(value: dependency_1.graphicData.CommonInfo) {
+ pb_1.Message.setWrapperField(this, 1, value);
+ }
+ get has_common() {
+ return pb_1.Message.getField(this, 1) != null;
+ }
+ get code() {
+ return pb_1.Message.getFieldWithDefault(this, 2, "") as string;
+ }
+ set code(value: string) {
+ pb_1.Message.setField(this, 2, value);
+ }
+ static fromObject(data: {
+ common?: ReturnType;
+ code?: string;
+ }): SignalFaultAlarm {
+ const message = new SignalFaultAlarm({});
+ if (data.common != null) {
+ message.common = dependency_1.graphicData.CommonInfo.fromObject(data.common);
+ }
+ if (data.code != null) {
+ message.code = data.code;
+ }
+ return message;
+ }
+ toObject() {
+ const data: {
+ common?: ReturnType;
+ code?: string;
+ } = {};
+ if (this.common != null) {
+ data.common = this.common.toObject();
+ }
+ if (this.code != null) {
+ data.code = this.code;
+ }
+ return data;
+ }
+ serialize(): Uint8Array;
+ serialize(w: pb_1.BinaryWriter): void;
+ serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
+ const writer = w || new pb_1.BinaryWriter();
+ if (this.has_common)
+ writer.writeMessage(1, this.common, () => this.common.serialize(writer));
+ if (this.code.length)
+ writer.writeString(2, this.code);
+ if (!w)
+ return writer.getResultBuffer();
+ }
+ static deserialize(bytes: Uint8Array | pb_1.BinaryReader): SignalFaultAlarm {
+ const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new SignalFaultAlarm();
+ while (reader.nextField()) {
+ if (reader.isEndGroup())
+ break;
+ switch (reader.getFieldNumber()) {
+ case 1:
+ reader.readMessage(message.common, () => message.common = dependency_1.graphicData.CommonInfo.deserialize(reader));
+ break;
+ case 2:
+ message.code = reader.readString();
+ break;
+ default: reader.skipField();
+ }
+ }
+ return message;
+ }
+ serializeBinary(): Uint8Array {
+ return this.serialize();
+ }
+ static deserializeBinary(bytes: Uint8Array): SignalFaultAlarm {
+ return SignalFaultAlarm.deserialize(bytes);
+ }
+ }
export class DeviceRelateRelay extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
diff --git a/src/protos/stationLayoutGraphics.ts b/src/protos/stationLayoutGraphics.ts
index c701c22..5c081bf 100644
--- a/src/protos/stationLayoutGraphics.ts
+++ b/src/protos/stationLayoutGraphics.ts
@@ -3515,7 +3515,8 @@ export namespace graphicData {
SectionLink = 4,
signal = 5,
station = 6,
- ScreenDoor = 7
+ ScreenDoor = 7,
+ SignalFaultAlarm = 8
}
export enum DevicePort {
A = 0,