aka_zaratustra

Мониторинг заряда PSS ver 1.5

May 6th, 2021 (edited)
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.19 KB | None | 0 0
  1. --Скрипт openComputers, для мониторинга заряда Power Sub-Station батарейки из GT++
  2. --Автор: aka_zaratustra весна 2021
  3. --Версия сборки под которую писался скрипт: GTNH 2.1.0.0-2.1.1.3
  4.  
  5. --Минимальная конфигурация компьютера openComputers - любой минимальный сэтап со сдвоенным монитором T1.
  6. --Для цветного вывода рекомендуемая конфигурация компьютера openComputers - Т2 видеокарта, сдвоенный монитор Т2, остальное может быть минимальным.
  7. --Адаптер с пустым внутренним слотом установлен в смежном блоке с контроллером Power Sub-Station.
  8. --Никаких других адаптеров, подключенных к греговским механизмам в сети компьютера openComputers быть не должно.
  9.  
  10. local ver = "1.5" -- версия программы
  11. --История изменений версий приведена внизу скрипта
  12.  
  13. --начальный режим работы мониторинга:
  14. --1 - сальдо расход/приход
  15. --2 - отдельно расход/приход
  16. local mode = 2
  17.  
  18.  
  19.  
  20. --разрешение монитора
  21. local Width = 20
  22. local Height = 4
  23. if mode == 2 then
  24.     Width = 22
  25. end
  26.  
  27. local component = require("component")
  28. local computer = require("computer")
  29. local event = require('event')
  30.  
  31.  
  32.  
  33. --local ADDRESS_PSS = "9885"
  34.  
  35.  
  36.    
  37. local object = {}
  38. object.PSS = {}
  39. local PSS = object.PSS
  40.  
  41. --Найдем компонент батареи
  42. for address, name in component.list("gt", false) do
  43.     local componentGT = component.proxy(address)
  44.     local info = componentGT.getSensorInformation()
  45.     if string.find(info[1], "substation") then
  46.         PSS.component = componentGT
  47.         --print(info[1])
  48.     end
  49. end
  50.  
  51. --PSS.component = component.proxy(component.get(ADDRESS_PSS))
  52. local gpu = component.gpu
  53.  
  54.  
  55.  
  56. local PrintChargePercent  --процент заряда батареи
  57. local PrintChargeAmount  -- количество заряда в eu
  58.  
  59. -- скорость изменения заряда eu/t
  60. local PrintChargeChange  
  61. local iChargeChange = 0
  62. local AvarageChargeChange = 0
  63.  
  64. -- скорость прихода и расхода заряда eu/t
  65. local PrintChargeIncome
  66. local iChargeIncome = 0
  67. local AvarageChargeIncome = 0
  68. local PrintChargeOutcome
  69. local iChargeOutcome = 0
  70. local AvarageChargeOutcome = 0
  71.  
  72.  
  73. local PrintChargeTime  -- время за которое произойдет полная зарядка/разрядка
  74.  
  75.  
  76. local LastTime = computer.uptime() -- счетчик времени
  77. local iLastChargeAmount = 0  -- количество заряда в eu, которое было на прошлой итерации
  78. local iLastChargeIncome = 0  -- количество притока заряда в eu, которое было на прошлой итерации
  79. local iLastChargeOutcome = 0  -- количество оттока заряда в eu, которое было на прошлой итерации
  80.  
  81. local AvarageDimSize = 10 -- количество хранимых последних значений скорости заряда. Используется для сглаживания скачков
  82. local current_i = 1
  83. local iChargeChangeDim = {} -- массив последних значений скорости зарядки
  84. --инициализируем массив
  85. for i = 1, AvarageDimSize do
  86.    iChargeChangeDim[i] = 0
  87. end
  88.  
  89. local iChargeIncomeDim = {} -- массив последних значений прихода заряда
  90. --инициализируем массив
  91. for i = 1, AvarageDimSize do
  92.    iChargeIncomeDim[i] = 0
  93. end
  94.  
  95. local iChargeOutcomeDim = {} -- массив последних значений расхода заряда
  96. --инициализируем массив
  97. for i = 1, AvarageDimSize do
  98.    iChargeOutcomeDim[i] = 0
  99. end
  100.  
  101.  
  102. local info = object.PSS.component.getSensorInformation() --получаем таблицу с текстом состояния батареи
  103.  
  104. function howManyYears(t) -- преобразовать секунды в количество лет, месяцев, дней, часов, минут, секунд
  105.  
  106.     if t < 60 then --если осталось меньше минуты
  107.         return tostring(math.floor(t)) .. " сек"
  108.     elseif t < 60*60 then --если осталось меньше часа
  109.         local minutes = math.floor(t/60)
  110.         local seconds = math.floor(math.fmod(t, 60))
  111.         return tostring(minutes) .. " мин " .. tostring(seconds) .. " сек"
  112.     elseif t < 60*60*24 then --если осталось меньше суток
  113.         local hours = math.floor(t/(60*60))
  114.         local minutes = math.floor(math.fmod(t, 60*60)/60)
  115.         return tostring(hours) .. " ч " .. tostring(minutes) .. " мин"
  116.     elseif t < 60*60*24*30 then --если осталось меньше месяца
  117.         local days = math.floor(t/(60*60*24))
  118.         local hours = math.floor(math.fmod(t, 60*60*24)/(60*60))
  119.         return  tostring(days) .. " д " .. tostring(hours) .. " ч"
  120.     elseif t < 60*60*24*30*12 then --если осталось меньше года
  121.         local months = math.floor(t/(60*60*24*30))
  122.         local days = math.floor(math.fmod(t, 60*60*24*30)/(60*60*24))
  123.         return  tostring(months) .. " мес " .. tostring(days) .. " д "
  124.     else --если осталось больше года
  125.         local years = math.floor(t/(60*60*24*30*12))
  126.         local months = math.floor(math.fmod(t, 60*60*24*30*12)/(60*60*24*30))
  127.         return  tostring(years) .. " г " .. tostring(months) .. " мес"
  128.     end
  129. end
  130.  
  131. function draw1() --отрисовать значения на экране по варианту 1
  132.     if gpu ~= nil then
  133.         gpu.fill(1,1,Width,Height,' ')
  134.         gpu.setForeground(0xFFFFFF)
  135.         gpu.set(1,1, "Заряд: "..PrintChargePercent)
  136.         gpu.set(1,2, "       "..PrintChargeAmount)
  137.         if AvarageChargeChange < 0 then
  138.             gpu.setForeground(0xFF0000)
  139.         elseif AvarageChargeChange > 0 then
  140.             gpu.setForeground(0x00FF00)
  141.         end
  142.         gpu.set(1,3, "       "..PrintChargeChange)
  143.         gpu.setForeground(0xFFFFFF)
  144.         gpu.set(1,4, "Время: "..PrintChargeTime)
  145.     end
  146. end
  147.  
  148. function draw2() --отрисовать значения на экране по варианту 2
  149.     if gpu ~= nil then
  150.         gpu.fill(1,1,Width,Height,' ')
  151.         gpu.setForeground(0xFFFFFF)
  152.         gpu.set(1,1, "Заряд:   "..PrintChargePercent)
  153.         gpu.set(1,2, "         "..PrintChargeAmount)
  154.  
  155.         if AvarageChargeIncome < 0 then
  156.             gpu.setForeground(0xFF0000)
  157.         elseif AvarageChargeIncome > 0 then
  158.             gpu.setForeground(0x00FF00)
  159.         end
  160.         local spaces = string.rep(" ", 9 - string.len(PrintChargeIncome))
  161.         gpu.set(1,3, spaces..PrintChargeIncome)    
  162.         gpu.setForeground(0xFFFFFF)
  163.        
  164.         if AvarageChargeOutcome < 0 then
  165.             gpu.setForeground(0xFF0000)
  166.         elseif AvarageChargeOutcome > 0 then
  167.             gpu.setForeground(0x00FF00)
  168.         end
  169.         local spaces = string.rep(" ", 9 - string.len(PrintChargeOutcome))
  170.         gpu.set(10,3, spaces..PrintChargeOutcome)
  171.        
  172.         gpu.setForeground(0xFFFFFF)
  173.         gpu.set(19,3, "eu/t")
  174.        
  175.         if AvarageChargeIncome + AvarageChargeOutcome < 0 then
  176.             gpu.setForeground(0xFF0000)
  177.         elseif AvarageChargeIncome + AvarageChargeOutcome > 0 then
  178.             gpu.setForeground(0x00FF00)
  179.         end
  180.         gpu.set(1,4, "Время:   "..PrintChargeTime)    
  181.     end
  182. end
  183.  
  184.  
  185. function formatGrade(n, postscriptum) --преобразует число в выводимую строку с сокращением триад 123456789 -> 123 M, присоединяет в концу строки второй параметр
  186.     local sn = ""
  187.     if math.abs(n) < 1000 then
  188.         sn = tostring(math.floor(n*100)/100).." "
  189.     elseif math.abs(n) < 1000000 then
  190.         sn = tostring(math.floor(n/10)/100).."K "
  191.     elseif math.abs(n) < 1000000000 then
  192.         sn = tostring(math.floor(n/10000)/100).."M "
  193.     elseif math.abs(n) < 1000000000000 then
  194.         sn = tostring(math.floor(n/10000000)/100).."G "
  195.     else
  196.         sn = tostring(math.floor(n/10000000000)/100).."T "
  197.     end
  198.     return sn..postscriptum
  199. end
  200.  
  201. function cutSpaces(s)
  202.     s,_ = s:gsub(' ','') --вырезаем пробелы (для 2.1.1.3)
  203.     s,_ = s:gsub(',','') --вырезаем запятые (для 2.1.1.0)
  204.     return s
  205. end
  206.  
  207. function update() --обновление инфы о состоянии батареи
  208.    
  209.  
  210.     --ротация по массиву значений последних значений изменения заряда
  211.     current_i = current_i + 1
  212.     if current_i > AvarageDimSize then
  213.         current_i = 1
  214.     end
  215.    
  216.     local ThisTime = computer.uptime()
  217.     local deltaTicks = (ThisTime - LastTime)*20 --сколько времени в тиках прошло после последнего обновления
  218.     LastTime = ThisTime
  219.     --print(deltaTicks)
  220.    
  221.  
  222.     info = object.PSS.component.getSensorInformation() --получаем таблицу с текстом состояния батареи
  223.  
  224.     --########################ДЛЯ ДЭБАГА
  225.     --for name, val in pairs(info) do --просмотрим таблицу
  226.         --print(name, val)
  227.         --os.sleep(0.5)
  228.     --end
  229.     --goto done
  230.     --########################
  231.  
  232.     local s = info[3] --строчка с текущим зарядом
  233.     s = string.sub(s,15,string.len(s)-3) --отрезаем лишние куски от строки
  234.     s = cutSpaces(s)
  235.     --print(s)
  236.     local iChargeAmount = tonumber(s)
  237.     --print(iChargeAmount)
  238.  
  239.     local s = info[10] --строчка с текущим приходом заряда
  240.     s = string.sub(s,16,string.len(s)-6) --отрезаем лишние куски от строки
  241.     s = cutSpaces(s)
  242.     --print(s)
  243.     local iChargeIncomeAmount = tonumber(s)
  244.     --print(iChargeIncomeAmount)
  245.  
  246.     local s = info[11] --строчка с текущим расходом заряда
  247.     s = string.sub(s,17,string.len(s)-6) --отрезаем лишние куски от строки
  248.     s = cutSpaces(s)
  249.     --print(s)
  250.     local iChargeOutcomeAmount = tonumber(s)
  251.     --print(iChargeOutcomeAmount)
  252.  
  253.  
  254.     local s = info[4] --строчка с полной емкостью батареи
  255.     s = string.sub(s,14,string.len(s)-3) --отрезаем лишние куски от строки
  256.     s = cutSpaces(s)
  257.     --print(s)
  258.     local iBatteryCap = tonumber(s)
  259.     --print(iBatteryCap)
  260.    
  261.     local dChargePercent = iChargeAmount / iBatteryCap * 100 --процент заряда батареи неокругленный
  262.     dChargePercent = math.floor(dChargePercent*100)/100 --округляем с масштабированием, так чтобы получилось два знака после запятой (например 33.33%)
  263.     PrintChargePercent = tostring(dChargePercent) .. " %"
  264.     --print(PrintChargePercent)
  265.  
  266.     PrintChargeAmount = formatGrade(iChargeAmount, "eu") --форматируем в выводимую строку
  267.    
  268.     --print(PrintChargeAmount)
  269.    
  270.     --
  271.     if iLastChargeAmount == 0 then
  272.         iLastChargeAmount = iChargeAmount
  273.     end
  274.     if iLastChargeIncome == 0 then
  275.         iLastChargeIncome = iChargeIncomeAmount
  276.     end
  277.     if iLastChargeOutcome == 0 then
  278.         iLastChargeOutcome = iChargeOutcomeAmount
  279.     end
  280.  
  281.    
  282.     iChargeChange = math.floor((iChargeAmount - iLastChargeAmount)/deltaTicks) -- скорость зарядки батареи в eu/t
  283.     iChargeIncome = math.floor((iChargeIncomeAmount - iLastChargeIncome)/deltaTicks) -- скорость зарядки батареи в eu/t
  284.     iChargeOutcome = -math.floor((iChargeOutcomeAmount - iLastChargeOutcome)/deltaTicks) -- скорость зарядки батареи в eu/t
  285.     --print(iChargeChange, iChargeAmount, iLastChargeAmount)
  286.    
  287.     --вычислим среднее значение скорости заряда исходя из последних AvarageDimSize значений
  288.     iChargeChangeDim[current_i] = iChargeChange
  289.     AvarageChargeChange = 0
  290.     for i = 1, AvarageDimSize do
  291.        AvarageChargeChange = AvarageChargeChange + iChargeChangeDim[i]
  292.        --print (i, iChargeChangeDim[i])
  293.     end
  294.     AvarageChargeChange = AvarageChargeChange / AvarageDimSize
  295.    
  296.     PrintChargeChange = formatGrade(AvarageChargeChange, "eu/t") --форматируем в выводимую строку
  297.        
  298.     if AvarageChargeChange > 0 then --добавим плюс в начале, если идет прирост энергии
  299.         PrintChargeChange = "+"..PrintChargeChange
  300.     end
  301.    
  302.     --вычислим среднее значение скорости прихода заряда исходя из последних AvarageDimSize значений
  303.     iChargeIncomeDim[current_i] = iChargeIncome
  304.     AvarageChargeIncome = 0
  305.     for i = 1, AvarageDimSize do
  306.        AvarageChargeIncome = AvarageChargeIncome + iChargeIncomeDim[i]
  307.        --print (i, iChargeChangeDim[i])
  308.     end
  309.     AvarageChargeIncome = AvarageChargeIncome / AvarageDimSize
  310.    
  311.     PrintChargeIncome = formatGrade(AvarageChargeIncome, "") --форматируем в выводимую строку
  312.        
  313.     if AvarageChargeIncome > 0 then --добавим плюс в начале, если идет прирост энергии
  314.         PrintChargeIncome = "+"..PrintChargeIncome
  315.     end
  316.    
  317.     --вычислим среднее значение скорости расхода заряда исходя из последних AvarageDimSize значений
  318.     iChargeOutcomeDim[current_i] = iChargeOutcome
  319.     AvarageChargeOutcome = 0
  320.     for i = 1, AvarageDimSize do
  321.        AvarageChargeOutcome = AvarageChargeOutcome + iChargeOutcomeDim[i]
  322.        --print (i, iChargeChangeDim[i])
  323.     end
  324.     AvarageChargeOutcome = AvarageChargeOutcome / AvarageDimSize
  325.    
  326.     PrintChargeOutcome = formatGrade(AvarageChargeOutcome, "") --форматируем в выводимую строку
  327.        
  328.     if AvarageChargeOutcome > 0 then --добавим плюс в начале, если идет прирост энергии
  329.         PrintChargeOutcome = "+"..PrintChargeOutcome
  330.     end
  331.    
  332.    
  333.     --print(PrintChargeChange)
  334.     iLastChargeAmount = iChargeAmount
  335.     iLastChargeIncome = iChargeIncomeAmount
  336.     iLastChargeOutcome = iChargeOutcomeAmount
  337.    
  338.     --время, оставшееся до полной зарядки или полной разрядки батареи
  339.     local ticksRemain
  340.     if AvarageChargeChange < 0 then --если батарея разряжается
  341.         ticksRemain = -iChargeAmount/AvarageChargeChange
  342.     elseif AvarageChargeChange > 0 then --если батарея заряжается
  343.         ticksRemain = (iBatteryCap - iChargeAmount)/AvarageChargeChange
  344.     else --если батарея разрядилась до нуля
  345.         ticksRemain = 0
  346.     end
  347.     --print(ticksRemain/20)
  348.     PrintChargeTime = howManyYears(ticksRemain/20)
  349.     --print(PrintChargeTime)
  350.    
  351.     --отрисовываем на экране вариант вывода в зависимости от выбранного режима
  352.     if mode == 1 then
  353.         draw1()
  354.     else   
  355.         draw2()
  356.     end
  357.     ::done::
  358. end
  359.  
  360.  
  361. local needToChangeMode = false
  362.  
  363. function handleEvent() --вызывается событием
  364.     needToChangeMode = true
  365. end
  366.  
  367. --for name, val in pairs(PSS.component) do --просмотрим таблицу
  368.         --print(name, val)
  369.         --os.sleep(2)
  370. --end
  371.  
  372. require("component").gpu.setResolution(Width, Height)
  373.  
  374.  
  375.  
  376. event.listen("key_down", handleEvent) -- listen for keypress
  377. while true do --вечный главный цикл программы
  378.     os.sleep(1)
  379.    
  380.     --если, пока спали, была нажата кнопка, то меняем режим
  381.     if needToChangeMode == true then
  382.         if mode == 1 then
  383.             mode = 2
  384.             Width = 22 --меняем ширину разрешения экрана, чтобы в режиме 2 все влезло на экран
  385.         else
  386.             mode = 1
  387.             Width = 20 --меняем ширину разрешения экрана на самый крупный
  388.         end
  389.         require("component").gpu.setResolution(Width, Height)
  390.         needToChangeMode = false
  391.     end
  392.    
  393.    
  394.     update() --выводим на экран инфу
  395.    
  396. end
  397.  
  398.  
  399.  
  400.  
  401. -- Версия 1.1
  402. -- Добавлены в вывод общего заряда и скорости заряда два разрадя после запятой: 12K eu/t -> 12.56K eu/t
  403. -- Указание ширины и высоты разрешения экрана вынесены в константы и указываются в начале скрипта
  404.  
  405. -- Версия 1.2
  406. -- Добавлено сглаживание значения скорости заряда батареи. Теперь выводится средняя скорость за последнее количество секунд, указанное в константе AvarageDimSize
  407. -- Устранена проблема отказа запуска программы из-за наличия вокруг блока адаптера других блоков Грега, например электрических проводов
  408.  
  409. -- Версия 1.3
  410. -- Добавлен режим вывода информации на экран, при котором входящая и исходящая скорости заряда батареи отображаются отдельно.
  411. -- Добавлена возможность переключения между режимами вывода информации на экран непосредственно во время работы программы. Переключение между режимами происходит по нажатию любой клавиши.
  412.  
  413. -- Версия 1.4
  414. -- Усовершенствованно цветовое отображение информации времени оставшегося до заряда/разряда батареи. Теперь время выводится зеленым если батарея заряжается, и красным если разряжается.
  415. -- Начальный режим работы мониторинга установлен в "отдельно расход/приход" (задается константой mode)
  416.  
  417. -- Версия 1.5
  418. -- Учтено изменение формата информации в таблице состояния батареи для версии 2.1.1.3 (на версии 2.1.1.0 разделители триад были запятые, а в 2.1.1.3 стали пробелом)
Add Comment
Please, Sign In to add comment