Advertisement
aka_zaratustra

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

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