Хорошо, есть много вещей, которые можно улучшить.Сначала давайте создадим SPLIT
функцию, которая преобразует тему в массив
FUNCTION SPLIT : ARRAY[0..255] OF STRING(250)
VAR_INPUT
STR: STRING(250);
CHAR: STRING(1);
END_VAR
VAR
iPos: INT;
sTest: STRING(250);
iIndex: INT;
xFinish: BOOL;
END_VAR
sTest := STR;
REPEAT
iPos := FIND(sTest, CHAR);
IF iPos = 0 THEN
SPLIT[iIndex] := sTest;
xFinish := TRUE;
ELSE
SPLIT[iIndex] := LEFT(sTest, iPos - 1);
sTest := RIGHT(sTest, LEN(sTest) - iPos);
END_IF;
iIndex := iIndex + 1;
UNTIL (xFinish = TRUE)
END_REPEAT;
END_FUNCTION
Теперь, как вы можете узнать, связана ли текущая тема с 'motion1'
VAR
arsTopic: ARRAY[0..255] OF STRING(250);
END_VAR
IF fbMessageQueue.nQueuedMessages > 0 THEN
IF fbMessageQueue.Dequeue(fbMessage:=fbMessage) THEN
fbMessage.GetTopic(pTopic:=ADR(sTopicRcv), nTopicSize := SIZEOF(sTopicRcv));
arsTopic := SPLIT(sTopicRcv, '/');
IF (arsTopic[0] = 'motion1') THEN
// do your staff
END_IF
END_IF
END_IF
Но так как вы затем загружаете разныеПолезные нагрузки для различных переменных Я хотел бы создать карту.Я не знаю всей вашей программы, но из того, что я вижу, я бы начал с:
TYPE SR_MOTION:
STRUCT
lrPostion: LREAL;
lrVelocity: LREAL;
lrAcceleration: LREAL;
lrDeceleration: LREAL;
lrExecute: LREAL;
END_STRUCT
END_TYPE
SR означает Сергей Романов, вы можете использовать любой префикс
Теперь давайте создадим вам массив движенийиметь.Допустим, у вас есть 3. Таким образом, мы отделяем число движения в отдельную переменную.Обратите внимание, что для того, чтобы ваш код работал плавно, не создавая большого количества ненужного кода, ваши темы должны быть не motion1/velocity
, а motion/1/velosity
.
VAR
astMotions: ARRAY[1..3] OF SR_MOTION;
arsTopic: ARRAY[0..255] OF STRING(250);
i: INT;
END_VAR
IF fbMessageQueue.nQueuedMessages > 0 THEN
IF fbMessageQueue.Dequeue(fbMessage:=fbMessage) THEN
fbMessage.GetTopic(pTopic:=ADR(sTopicRcv), nTopicSize := SIZEOF(sTopicRcv));
fbMessage.GetPayload(pPayload:=ADR(sPayloadRcv), nPayloadSize:=SIZEOF(sPayloadRcv), bSetNullTermination:=TRUE);
arsTopic := SPLIT(sTopicRcv, '/');
IF arsTopic[0] = 'machine' THEN
IF arsTopic[1] = 'on' THEN
Machine.bOnPB := STRING_TO_BOOL(sPayloadRcv);
ELSIF arsTopic[1] = 'off' THEN
Machine.bOffPB := STRING_TO_BOOL(sPayloadRcv);
END_IF
ELSIF arsTopic[0] = 'motion' THEN
i := STRING_TO_INT(arsTopic[1]); // arsTopic[1] has motion number in `motion/1/velosity`
IF arsTopic[2] = 'position' THEN
astMotions[i].lrPosition := STRING_TO_LREAL(sPayloadRcv);
ELSIF arsTopic[2] = 'velosity' THEN
astMotions[i].lrVelosity := STRING_TO_LREAL(sPayloadRcv);
ELSIF arsTopic[2] = 'acceleration' THEN
astMotions[i].lrAcceleration := STRING_TO_LREAL(sPayloadRcv);
ELSIF arsTopic[2] = 'Deceleration' THEN
astMotions[i].lrDeceleration := STRING_TO_LREAL(sPayloadRcv);
ELSIF arsTopic[2] = 'execute' THEN
astMotions[i].lrExecute := STRING_TO_LREAL(sPayloadRcv);
END_IF
END_IF
END_IF
END_IF
Вот весь ваш код для всех 3 движений.
Редактировать: добавить вычитание числа из темы
Если вы не хотите менять темы на motion/1/velosity
, вы можете использовать эту функцию, которая будет извлекать последний символ и преобразовываться в int
FUNCTION TOPIC_TO_INT: INT
VAR_INPUT
str: STRING;
END_VAR
VAR
ps: POINTER TO ARRAY[0..200] OF BYTE;
END_VAR
ps := ADR(str);
TOPIC_TO_INT := BYTE_TO_INT(ps^[LEN(str) - 1]) - 48;
END_FUNCTION
И тогда в коде вместо i := STRING_TO_INT(arsTopic[1]);
вы можете i := TOPIC_TO_INT(arsTopic[0])
, а остальная часть кода слегка изменится.
Так что если вы используете TOPIC_TO_INT(STRING#'message2')
, эта функция вернет INT#2