Исторически с версией 0.5 я не смог заставить локомотив с составом идентифицировать сообщения АЛС поступающих к нему и спереди и сзади. Чтобы он получал сообщения только с одной стороны – головы поезда и при движении назад и чтобы это было достаточно общим решением, зависящим только от того, где у состава "сценарный" перед и должны ли от светофора со стороны активной кабины доходить в лок путевые сообщения. Поэтому в v0.6 формат был изменен. По мере углубления моих знаний о режимах АЛСН и работе КЛУБа (Спасибо, Стас!), может быть, я сам уже подозреваю сообщения v0.6 в избыточности, но в качестве побочного занятного эффекта они дают хоть на 50%, но сделать похожим на правду работу ЭК в КЛУБе. Но это оффтоп.
Приведенный скрипт с функцией обработки сообщений светофоров приведен практически без изменений по сравнению с работающим проектом, и не включает в себя саму индикацию огней, т.к. она связана с ЭПК, и это сделано отдельной функцией. Дополнительно нужно при индикации проверять не находится ли лок с активной кабина в положении толкача и может быть другие условия. Да, есть некоторые проблемы с системой СВЕТОФОРv06 – АЛСН в некоторых ситуациях. Но он в целом применим для оживления АЛСН, естественно с необходимыми модификациями для конкретного проекта.
Если написание комментов ничего не сломало, то можно вставить весь текст в Loco_EngineScript. и сделать в системной OnCustomSignalMessage(ConsistMessage) вызов tALS:GetSignal(ConsistMessage)
- Код: Выделить всё
function OnCustomSignalMessage(ConsistMessage)
tALS:GetSignal(ConsistMessage)
end
Скрипт:
- Код: Выделить всё
------------------------------------------------------------
-- типо версия модуля АЛСН
BVU_4_K773 = "18.12.15_20.40"
------------------------------------------------------------
-- таблица с ключами, которые описывают работу АЛСН
tALS = {
-- индекс для таблицы tALS.OnCoil (см. далее) задающий частоту приемника в локе по умолчанию
Receiver = 2,
-- индекс для таблицы tALS.OnRail (см. далее) показывающий, какая частота "на рельсах" по умолчанию (false означает, что сигнала с рельс нет)
Emitter = false,
-- ключ для хранения времени последнего получения сигнала с рельс
LastTime = 0,
-- таблица со значениями возможных частот приемника. "ty" частота задается электронной картой
OnCoil = {25, 50, 75, "ty"},
-- таблица со значениями возможных символов в обозначении светофоров (Identity) задающих частоту АЛС
-- индексы в таблицах tALS.OnCoil и tALS.OnRail "синхронизированы", т.е. символу "*" светофора соответствует частота 25 (Гц)
OnRail = {"*", "~", "=", "+" },
-- таблица с состояниями огней АЛСН в локе (1 = ВКЛ, 0 = ВЫКЛ)
Lights = {["white"]=0, ["red"]=0, ["kg"]=0, ["yellow"]=0, ["green1"]=0, ["green2"]=0, ["green3"]=0, ["green4"]=0},
-- ключ для хранения состояния АЛСН (используется другими частями скрипта лока)
-- false = ВЫКЛ; true = ВКЛ, но сигнала АЛС нет, 0, 1, 2, для указания текущего активного огня
State = false,
-- ключ для хранения предыдущего показания при смене огней
Prev = false,
-- ключ для хранения информации о пересечении границы БУ
Border = false,
-- ключ для хранении имени светофора
Name = "",
-- ключ для преобразования римских цифр в обозначении светофора в арабские
Convert = {"!" , "@" , "#" , "$" , "%" , "^" , "&"},
-- ключ для хранения расстояния до светофора
Distance = "",
-- ключ для хранения передаваемого светофором ограничения скорости
Limit = false
}
------------------------------------------------------------
frame = 0 -- номер кадра для лога при отладке.
------------------------------------------------------------
-- функция, вызываемая каждый кадр из системной функции OnCustomSignalMessage(ConsistMessage) скрипта локомотива как:
--[[
function OnCustomSignalMessage(ConsistMessage)
tALS:GetSignal(ConsistMessage)
end
]]
function tALS:GetSignal(ConsistMessage)
frame = frame + 1 -- счетчик кадров
-- запись в лог
--logfile:write("\n"..frame.." OCSM.1 ".. ConsistMessage .." CounterOCSM="..tostring(CounterOCSM))
--
-- определение первого символа полученного сообщения
MessageFlag = string.sub(ConsistMessage, 1, 1)
-- если символ = латинская F или B то это сообщение АЛС (E для маркера станции при работе КЛУБ с ЭК. Предполагается, что S для САУТ)
if MessageFlag == "F" or MessageFlag == "B" then
-- поиск служебных символов "*", "~", "=", "+" и присвоение ключу tALS.Emitter номера индекса таблицы tALS.OnRail, соответствующему этому символу
for i = 1, 4 do
if string.find (ConsistMessage, tALS.OnRail[i]) then
tALS.Emitter = i
-- определение позиции этого служебного символа в переданном сообщении
signSeparator = string.find(ConsistMessage, tALS.OnRail[i])
end
end --logfile:write("\n "..tostring(tALS.Emitter).." "..tostring(tAutostop.State))
-- УСЛОВИЕ 1. если включен ЭПК (закомментировано, т.е. по факту не проверяется) и "частоты приемника АЛС" и "частоты на рельсе" совпали, то начинается обработка сообщения светофора
if --[[tAutostop.State and]] tALS.Emitter == tALS.Receiver then --logfile:write("\n tAutostop.State and tALS.Emitter == tALS.Receiver")
-- счетчик полученных в течение кадра сообщений (каждый кадр может быть принято до двух сообщений от светофоров (при правильной их работе), поэтому надо учесть все сообщения)
CounterOCSM = CounterOCSM + 1
-- если сообщение получено спереди состава
if MessageFlag == "F" then
-- вспомогательная переменная с именем светофора спереди
SignalF = string.sub(ConsistMessage, 11)
-- вспомогательная переменная с сообщением светофора спереди
ConsistMessageF = ConsistMessage
-- если ранее АЛСН была выключена или сообщений не было, то за светофор, показания которого будут отображаться на АЛСН принимается светофор спереди.
if ALSNSignal == "" then ALSNSignal = SignalF end
-- если сообщение получено сзади состава
elseif MessageFlag == "B" then
-- вспомогательные переменные именем светофора сзади и сообщением от него
SignalB = string.sub(ConsistMessage, 11)
ConsistMessageB = ConsistMessage
end
--
--logfile:write("\n"..frame.." OCSM.2 ".. ConsistMessage .." CounterOCSM="..tostring(CounterOCSM)..tALS:Debug())
--
-- если получены два сообщения, то идет дальнейшая обработка
-- если светофоров два с двух сторон, то это разные сообщения, если светофор один, то получено два одинаковых сообщения
if CounterOCSM == 2 then
--logfile:write("\n OCSM.4 CounterOCSM = 2")
-- обнуление счетчика
CounterOCSM = 0
-- проверка смены БУ при движении поезда
if Call("*:GetControlValue", "SpeedometerKPH", 0) > 0.05 then
-- если сменилось имя светофора спереди,
-- перед этим сообщение АЛС поступало спереди,
-- при этом имя светофора сзади не изменилось (или же его нет совсем, тогда SignalB = prevSignalB = "")
-- то состав вступает на новый БУ и сообщение АЛС = сообщение от "нового светофора" спереди
-- понятия СПЕРЕДИ и СЗАДИ это понятия относительно вектора движения поезда, т.е. к какому светофору едет поезл, тот и будет светофором спереди, вне зависимости от того хвост ли это или голова поезда в привычном понимании. это особенность работы движка РВ.
if SignalB == prevSignalB and ALSNSignal == prevSignalF and ALSNSignal~= SignalF and ALSNSignal~= SignalB then ALSNSignal, tALS.Border = SignalF, true
--
--logfile:write("\n OCSM.3 BORDER FRONT")
--
-- если сменилось имя светофора сзади,
-- перед этим сообщение АЛС поступало сзади,
-- при этом имя светофора спереди не изменилось (или же его нет совсем, тогда SignalF = prevSignalF = "")
-- то сообщение АЛС = сообщение от "нового светофора" спереди
elseif SignalF == prevSignalF and ALSNSignal == prevSignalB and ALSNSignal~= SignalB and ALSNSignal~= SignalF then ALSNSignal = SignalB
--
--logfile:write("\n OCSM.4 BORDER REAR")
--
end
end
-- если поезд находится между двумя светофорами, посылющими сообщения
if SignalF ~= SignalB and SignalF ~= "" and SignalB ~= "" then
--
--logfile:write("\n OCSM.5 BORDER FRONT")
--
-- если сменился вектор движения поезда, то для РВ светофор спереди стал светофором сзади и наоборот
-- а нужно чтобы лок по прежнему получал сообщение от того же самого светофора
-- поэтому если он обрабатывал сообщения спереди, то теперь он будет обрабатывать сообщения сзади
if SignalB == prevSignalF and ALSNSignal == prevSignalF then ALSNSignal = SignalB end
-- поэтому если он обрабатывал сообщения сзади, то теперь он будет обрабатывать сообщения спереди
if SignalF == prevSignalB and ALSNSignal == prevSignalB then ALSNSignal = SignalF end
-- и в качестве сообщения для обработки принимается сообщение от соотвествующего светофора
if SignalF == ALSNSignal and SignalB ~= ALSNSignal then ConsistMessage = ConsistMessageF end
if SignalB == ALSNSignal and SignalF ~= ALSNSignal then ConsistMessage = ConsistMessageB end
end
--logfile:write("\n"..frame.." OCSM.4 newCM ".. ConsistMessage ..tALS:Debug())
-- фиксируется время поступления последенго сообщения на обработку
tALS.LastTime = gSimulationTime
-- из сообщения извлекается показание светофора
tALS.State = tonumber(string.sub(ConsistMessage,2,3))
-- если показание светофора с нижним желтым огнем (движение с отклонением), то на АЛСН горит Ж
if tALS.State > 10 then tALS.State = 1 end
--if SignalState ~= 0 then SignalSpeedLimit = tonumber(string.sub(ConsistMessage, 4, 6)) else SignalSpeedLimit = 20 end logfile:write("\n51 ConsistMessage "..tostring(ConsistMessage).." SignalSpeedLimit "..SignalSpeedLimit)
-- извлечение из сообщения ограничения скорости (на линке или на треке)
tALS.Limit = tonumber(string.sub(ConsistMessage, 4, 6))
-- если показание светофора К, то ограничение 20 км/ч
if tALS.State == 0 then tALS.Limit = 20 end
-- извлечение из сообщения расстояния до светофора
tALS.Distance = string.sub(ConsistMessage, 7, 10)
-- извлевение собственно имени для отображения на КЛУБе
tALS.Name = string.sub(ConsistMessage, 11, signSeparator - 1)
-- конвертация латинских цифр в арабские
local latin = string.sub(tALS.Name, 1, 1)
if latin == "!" or latin == "@" or latin == "#" or latin == "$" or latin == "%" or latin == "^" or latin == "&" then tALS.Name = string.sub(tALS.Name, 2) end
local latin = string.sub(tALS.Name, -1, -1)
if latin == "!" or latin == "@" or latin == "#" or latin == "$" or latin == "%" or latin == "^" or latin == "&" then
for k, v in ipairs(tALS.Convert) do
if latin == v then tALS.Name = string.gsub(tALS.Name, latin, tostring(k)) end
end
end
-- обновление переменных
prevSignalF, prevSignalB = SignalF, SignalB
end
-- если не выполнено УСЛОВИЕ 1 (ЭПК выключен ИЛИ "частоты приемника АЛС" и "частоты на рельсе" не совпали то сброс всех вспомогательных переменных
else
CounterOCSM = 0
SignalF, prevSignalF, ConsistMessageF, SignalB, prevSignalB, ConsistMessageB, ALSNSignal = "", "", "", "", "", "", ""
-- SignalF текущий светофор спереди
-- prevSignalF предыдущий светофор спереди
-- ConsistMessageF сообщение от текущего светофор спереди
-- SignalB текущий светофор сзади
-- prevSignalB предыдущий светофор сзади
-- ConsistMessageB сообщение от текущего светофор сзади
-- ALSNSignal светофор ,сообщение которого обрабатывается.
end
--logfile:write("\n OnCustomSignalMessage end "..tALS.State)
end
end -- OnCustomSignalMessage