В качестве пояснения. Исторически с версией 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
|