분 추가 (스케쥴 new 추가 필요)
This commit is contained in:
parent
cd7620672f
commit
eb3bc33509
|
|
@ -4,6 +4,16 @@ class ModbusController < ApplicationController
|
|||
@modbus_running = Modbus::PollingService.running?
|
||||
end
|
||||
|
||||
def destroy
|
||||
schedule = Schedule.find_by(id: params[:id])
|
||||
|
||||
if schedule.destroy
|
||||
redirect_to schedule_edit_modbus_index_path, notice: "스케줄이 삭제되었습니다."
|
||||
else
|
||||
redirect_to schedule_edit_modbus_index_path, alert: "스케줄 삭제에 실패했습니다."
|
||||
end
|
||||
end
|
||||
|
||||
def start
|
||||
Modbus::PollingService.start
|
||||
redirect_to modbus_index_path
|
||||
|
|
@ -19,17 +29,23 @@ class ModbusController < ApplicationController
|
|||
end
|
||||
|
||||
def schedule_edit_update
|
||||
error_hours = []
|
||||
error_time = []
|
||||
|
||||
params[:schedule].each do |id, attributes|
|
||||
schedule = Schedule.find_by(id: id)
|
||||
unless schedule.update(temperature: attributes[:temperature])
|
||||
error_hours << "#{schedule.hour}시"
|
||||
unless schedule.update(
|
||||
hour: attributes[:hour],
|
||||
minute: attributes[:minute],
|
||||
is_active: attributes[:is_active],
|
||||
temperature: attributes[:temperature]
|
||||
)
|
||||
|
||||
error_time << "#{schedule.hour}시 #{schedule.minute}분"
|
||||
end
|
||||
end
|
||||
|
||||
if error_hours.any?
|
||||
redirect_to modbus_index_path, alert: "#{error_hours.join(', ')}의 온도 업데이트에 실패하였습니다."
|
||||
if error_time.any?
|
||||
redirect_to modbus_index_path, alert: "#{error_time.join(', ')}의 온도 업데이트에 실패하였습니다."
|
||||
else
|
||||
redirect_to modbus_index_path, notice: "스케줄이 성공적으로 업데이트되었습니다."
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
class Schedule < ApplicationRecord
|
||||
validates :hour, presence: true
|
||||
validates :minute, presence: true
|
||||
validates :temperature,
|
||||
presence: true,
|
||||
numericality: true,
|
||||
format: { with: /\A\d+(\.\d)?\z/ }
|
||||
validates :minute, uniqueness: { scope: :hour }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,45 +3,68 @@ module Modbus
|
|||
class << self
|
||||
def start
|
||||
return if $modbus_polling_threads.any?(&:alive?)
|
||||
|
||||
thread = Thread.new do
|
||||
puts "[#{Time.current}] Modbus polling service 시작됨"
|
||||
last_logged_hour = nil
|
||||
loop do
|
||||
begin
|
||||
now = Time.now
|
||||
current_hour = now.hour
|
||||
|
||||
if current_hour != last_logged_hour && now.min == 0
|
||||
schedule = Schedule.find_by(hour: current_hour)
|
||||
|
||||
serial_path = Rails.root.join("serial.rb")
|
||||
system("ruby", serial_path.to_s, "#{schedule.temperature * 10}")
|
||||
|
||||
puts "[Schedule] #{current_hour}:00 -> Target temp: #{schedule.temperature}°C"
|
||||
last_logged_hour = current_hour
|
||||
end
|
||||
rescue StandardError => e
|
||||
error_message = "[#{Time.current}] 오류: #{e.message}"
|
||||
|
||||
puts error_message
|
||||
ensure
|
||||
sleep 0.1
|
||||
end
|
||||
end
|
||||
end
|
||||
$modbus_polling_threads << thread
|
||||
$modbus_polling_threads << start_thread
|
||||
end
|
||||
|
||||
def stop
|
||||
$modbus_polling_threads.each { |t| t.kill if t.alive? }
|
||||
$modbus_polling_threads.clear
|
||||
puts "[#{Time.now}] Modbus polling service 중지됨"
|
||||
puts "Modbus polling service 중지됨"
|
||||
end
|
||||
|
||||
def running?
|
||||
$modbus_polling_threads.any?(&:alive?)
|
||||
end
|
||||
|
||||
private
|
||||
def start_thread
|
||||
Thread.new { run_polling_loop }
|
||||
end
|
||||
|
||||
def run_polling_loop
|
||||
puts "Modbus polling service 시작됨"
|
||||
last_logged = nil
|
||||
|
||||
loop do
|
||||
begin
|
||||
now = Time.now
|
||||
current = [ now.hour, now.min ]
|
||||
|
||||
if current != last_logged
|
||||
puts "시간 변경 감지됨: #{current.join(':')}"
|
||||
schedule = Schedule.find_by(hour: current[0], minute: current[1])
|
||||
apply_schedule(schedule) if schedule
|
||||
last_logged = current
|
||||
end
|
||||
rescue => e
|
||||
puts "[#{Time.current}] #{file} 에러: #{e.message}"
|
||||
ensure
|
||||
sleep 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def apply_schedule(schedule)
|
||||
if schedule.is_active
|
||||
run_script("on_off.rb", "0", "[Schedule] ON")
|
||||
run_script(
|
||||
"serial.rb",
|
||||
(schedule.temperature * 10).to_i.to_s,
|
||||
"[Schedule] #{schedule.hour}:#{schedule.minute} → #{schedule.temperature}°C"
|
||||
)
|
||||
else
|
||||
run_script("on_off.rb", "1", "[Schedule] OFF")
|
||||
end
|
||||
end
|
||||
|
||||
def run_script(file, arg, success_msg)
|
||||
path = Rails.root.join(file)
|
||||
if system("ruby", path.to_s, arg)
|
||||
puts success_msg
|
||||
else
|
||||
puts "[#{Time.current}] #{file} 실행 실패 (args: #{arg})"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,12 +23,21 @@
|
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
|
||||
</head>
|
||||
|
||||
<body class="h-screen">
|
||||
<body>
|
||||
<%= turbo_frame_tag :modals %>
|
||||
<main class="flex flex-col h-full divide-y divide-border-table-border">
|
||||
<%= render "partials/header" %>
|
||||
<div class="flex flex-row flex-1 w-full divide-x divide-border-table-border">
|
||||
<div class="w-full h-full">
|
||||
<% if flash[:notice] %>
|
||||
<div class="m-4 rounded px-4 py-2 bg-accept text-white">
|
||||
<%= flash[:notice] %>
|
||||
</div>
|
||||
<% elsif flash[:alert] %>
|
||||
<div class="m-4 rounded px-4 py-2 bg-danger text-white">
|
||||
<%= flash[:alert] %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= yield %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
<% if flash[:notice] %>
|
||||
<div class="m-4 rounded px-4 py-2 bg-accept text-white">
|
||||
<%= flash[:notice] %>
|
||||
</div>
|
||||
<% elsif flash[:alert] %>
|
||||
<div class="m-4 rounded px-4 py-2 bg-danger text-white">
|
||||
<%= flash[:alert] %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="flex flex-col h-full divide-y divide-border-table-border">
|
||||
<div class="flex flex-col flex-1 p-4 space-y-4">
|
||||
<table class="base-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>시간</th>
|
||||
<th>분</th>
|
||||
<th>사용여부</th>
|
||||
<th>온도</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -20,6 +13,8 @@
|
|||
<% @schedule.each do |s| %>
|
||||
<tr>
|
||||
<td><%= s.hour %>시</td>
|
||||
<td><%= s.minute %>분</td>
|
||||
<td><%= s.is_active %></td>
|
||||
<td><%= s.temperature %> °C</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -4,15 +4,30 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>시간</th>
|
||||
<th>분</th>
|
||||
<th>사용여부</th>
|
||||
<th>온도</th>
|
||||
<th>삭제</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @schedule.each do |s| %>
|
||||
<tr>
|
||||
<td><%= s.hour %>시</td>
|
||||
<td><%= number_field_tag "schedule[#{s.id}][temperature]", s.temperature, step: "0.1", inputmode: "decimal", class: "border px-2 py-1 rounded" %>
|
||||
°C
|
||||
<td>
|
||||
<%= select_tag "schedule[#{s.id}][hour]",
|
||||
options_for_select((0..23).map { |h| [h.to_s.rjust(2, '0'), h] }, s.hour),
|
||||
class: "input-style" %>
|
||||
</td>
|
||||
<td><%= number_field_tag "schedule[#{s.id}][minute]", s.minute, min: 0, max: 59, step: 1, inputmode: "decimal", class: "input-style" %></td>
|
||||
<td><%= check_box_tag "schedule[#{s.id}][is_active]", "1", s.is_active == true || s.is_active == 1 %></td>
|
||||
<td><%= number_field_tag "schedule[#{s.id}][temperature]", s.temperature, step: "0.1", inputmode: "decimal", class: "input-style" %></td>
|
||||
<td>
|
||||
<%= link_to "삭제", modbus_path(s),
|
||||
data: {
|
||||
turbo_method: :delete,
|
||||
turbo_confirm: "정말 삭제하시겠습니까?"
|
||||
},
|
||||
class: "btn bg-danger text-sm" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ class CreateSchedules < ActiveRecord::Migration[8.0]
|
|||
def change
|
||||
create_table :schedules do |t|
|
||||
t.integer :hour
|
||||
t.integer :minute
|
||||
t.boolean :is_active
|
||||
t.float :temperature
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :schedules, [ :hour, :minute ], unique: true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@
|
|||
ActiveRecord::Schema[8.0].define(version: 2025_04_16_131440) do
|
||||
create_table "schedules", force: :cascade do |t|
|
||||
t.integer "hour"
|
||||
t.integer "minute"
|
||||
t.boolean "is_active"
|
||||
t.float "temperature"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["hour", "minute"], name: "index_schedules_on_hour_and_minute", unique: true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@
|
|||
# end
|
||||
|
||||
(0..23).each do | h |
|
||||
Schedule.create!(hour: h, temperature: 15.0)
|
||||
Schedule.create!(hour: h, minute: 0, is_active: true, temperature: 15.0)
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue