diff --git a/app/controllers/modals_controller.rb b/app/controllers/modals_controller.rb index 7cdfe77..7ccb852 100644 --- a/app/controllers/modals_controller.rb +++ b/app/controllers/modals_controller.rb @@ -1,6 +1,6 @@ class ModalsController < ApplicationController def open @schedule = Schedule.new - render partial: "partials/modals_open", locals: { type: params[:type], close_button: params[:close_button] } + render partial: "partials/modals_open", locals: { type: params[:type], id: params[:id], close_button: params[:close_button] } end end diff --git a/app/controllers/modbus_controller.rb b/app/controllers/modbus_controller.rb index fb3f7a7..a943e5d 100644 --- a/app/controllers/modbus_controller.rb +++ b/app/controllers/modbus_controller.rb @@ -1,11 +1,2 @@ class ModbusController < ApplicationController - def start - Modbus::PollingService.start - redirect_to schedules_path - end - - def stop - Modbus::PollingService.stop - redirect_to schedules_path - end end diff --git a/app/controllers/schedules_controller.rb b/app/controllers/schedules_controller.rb index 4390cb1..ae0c44e 100644 --- a/app/controllers/schedules_controller.rb +++ b/app/controllers/schedules_controller.rb @@ -1,6 +1,11 @@ class SchedulesController < ApplicationController def index - @schedule = Schedule.order(:hour, :minute) + @controllers = Controller.all + end + + def view + @controller = Controller.find(params[:id]) + @schedule = Schedule.where(controller_id: params[:id]).order(:hour, :minute) @modbus_running = Modbus::PollingService.running? end @@ -12,10 +17,10 @@ class SchedulesController < ApplicationController @schedule = Schedule.new(schedule_params) if @schedule.save - redirect_to schedule_edit_schedules_path, notice: "스케쥴이 추가 되었습니다." + redirect_to schedule_edit_schedule_path(@schedule.controller_id), notice: "스케쥴이 추가 되었습니다." else error_messages = @schedule.errors.full_messages.join(", ") - redirect_to schedule_edit_schedules_path, alert: "스케쥴 추가 실패: #{error_messages}" + redirect_to schedule_edit_schedule_path(@schedule.controller_id), alert: "스케쥴 추가 실패: #{error_messages}" end end @@ -23,23 +28,23 @@ class SchedulesController < ApplicationController @schedule = Schedule.find_by(id: params[:id]) if @schedule.destroy - redirect_to schedule_edit_schedules_path, notice: "스케줄이 삭제되었습니다." + redirect_to schedule_edit_schedule_path(@schedule.controller_id), notice: "스케줄이 삭제되었습니다." else error_messages = @schedule.errors.full_messages.join(", ") - redirect_to schedule_edit_schedules_path, alert: "스케쥴 삭제 실패: #{error_messages}" + redirect_to schedule_edit_schedule_path(@schedule.controller_id), alert: "스케쥴 삭제 실패: #{error_messages}" end end def reset - Schedule.delete_all + Schedule.where(controller_id: params[:id]).destroy_all ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence WHERE name='schedules'") - Rails.application.load_seed - redirect_to schedules_path, notice: "스케줄이 초기화되었습니다." + redirect_to schedule_edit_schedule_path(params[:id]), notice: "스케줄이 초기화되었습니다." end def schedule_edit - @schedule = Schedule.order(:hour, :minute) + @controller = Controller.find(params[:id]) + @schedule = Schedule.where(controller_id: params[:id]).order(:hour, :minute) end def schedule_edit_update @@ -63,14 +68,14 @@ class SchedulesController < ApplicationController end if error_messages.any? - redirect_to schedules_path, alert: error_messages.join("
") + redirect_to schedule_edit_schedule_path(params[:controller_id]), alert: error_messages.join("
") else - redirect_to schedules_path, notice: "스케줄이 성공적으로 업데이트되었습니다." + redirect_to schedule_edit_schedule_path(params[:controller_id]), notice: "스케줄이 성공적으로 업데이트되었습니다." end end private def schedule_params - params.require(:schedule).permit(:hour, :minute, :is_active, :temperature) + params.require(:schedule).permit(:controller_id, :hour, :minute, :is_active, :temperature) end end diff --git a/app/models/schedule.rb b/app/models/schedule.rb index b8d23ca..0322bdf 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -5,5 +5,5 @@ class Schedule < ApplicationRecord presence: { message: "온도를 입력하세요" }, numericality: { message: "온도는 숫자여야 합니다" }, format: { with: /\A\d+(\.\d)?\z/, message: "온도는 소수점 한 자리까지 입력 가능합니다" } - validates :minute, uniqueness: { scope: :hour, message: "같은 시:분의 스케쥴이 이미 존재합니다" } + validates :minute, uniqueness: { scope: [ :controller_id, :hour ], message: "같은 시:분의 스케쥴이 이미 존재합니다" } end diff --git a/app/services/modbus/polling_service.rb b/app/services/modbus/polling_service.rb index b981e70..a96f8c8 100644 --- a/app/services/modbus/polling_service.rb +++ b/app/services/modbus/polling_service.rb @@ -14,47 +14,34 @@ module Modbus now = Time.now current_time = format("%02d:%02d", now.hour, now.min) puts "# current time: #{current_time}.#{now.sec}" - schedule = Schedule.find_by(hour: now.hour, minute: now.min) - apply_schedule(schedule) if schedule + schedules = Schedule.where(hour: now.hour, minute: now.min) + schedules.each { |schedule| apply_schedule(schedule) } end end - def stop - if defined?(@scheduler) - @scheduler.shutdown(:kill) - @scheduler = nil - puts "[#{Time.now}] Modbus polling service 중지됨" - else - puts "[#{Time.now}] Scheduler 인스턴스 없음" - end - end - - def running? - @scheduler - end - private def apply_schedule(schedule) if schedule.is_active - run_script("on_off.rb", "0", "[Schedule] ON") + run_script("on_off.rb", "#{schedule.controller.station_id}", "0", "[Schedule] ON") sleep 2 run_script( "serial.rb", + "#{schedule.controller.station_id}", (schedule.temperature * 10).to_i.to_s, "[Schedule] #{format('%02d:%02d', schedule.hour, schedule.minute)} → #{schedule.temperature}°C" ) else - run_script("on_off.rb", "1", "[Schedule] OFF") + run_script("on_off.rb", "#{schedule.controller.station_id}", "1", "[Schedule] OFF") end end - def run_script(file, arg, success_msg) + def run_script(file, controller_id, value, success_msg) path = Rails.root.join(file) - if system("ruby", path.to_s, arg) + if system("ruby", path.to_s, controller_id, value) puts success_msg Rails.logger.info success_msg else - error_message = "[#{Time.now}] #{file} 실행 실패 (args: #{arg})" + error_message = "[#{Time.now}] #{file} 실행 실패 (value: #{value})" puts error_message Rails.logger.error error_message end diff --git a/app/views/partials/modals/_add_schedule.html.erb b/app/views/partials/modals/_add_schedule.html.erb index 7e7b284..db25ecd 100644 --- a/app/views/partials/modals/_add_schedule.html.erb +++ b/app/views/partials/modals/_add_schedule.html.erb @@ -1,5 +1,7 @@ <%= form_with model: @schedule, method: :post, data: { turbo: false }, class: 'flex flex-col h-full divide-y divide-border-table-border' do |form| %> + <%= form.hidden_field :controller_id, value: params[:id] %>
+ <%= Controller.find(params[:id]).name %> 컨트롤러 diff --git a/app/views/schedules/index.html.erb b/app/views/schedules/index.html.erb index 444599f..748fa05 100644 --- a/app/views/schedules/index.html.erb +++ b/app/views/schedules/index.html.erb @@ -1,42 +1,7 @@ -
-
-
- - - - - - - - - - <% @schedule.each do |s| %> - - - - - - - <% end %> - -
시간사용여부온도
<%= s.hour %>시<%= s.minute %>분<%= s.is_active %><%= s.temperature %> °C
-
-
- <%= button_to "스케쥴러 시작", start_modbus_index_path, method: :post, class: "btn bg-accept" %> - <%= button_to "스케쥴러 정지", stop_modbus_index_path, method: :post, class: "btn bg-danger" %> -
- -
- 스케쥴러 상태: - <% if @modbus_running %> - 실행 중 - <% else %> - 정지됨 - <% end %> -
-
-
-
- <%= link_to "수정", schedule_edit_schedules_path, class: "btn bg-default-slate" %> +
+
+ <% @controllers.each do |c| %> + <%= link_to c.name, view_schedule_path(c.id), class: "btn bg-primary" %> + <% end %>
diff --git a/app/views/schedules/schedule_edit.html.erb b/app/views/schedules/schedule_edit.html.erb index 8aebd07..abbf621 100644 --- a/app/views/schedules/schedule_edit.html.erb +++ b/app/views/schedules/schedule_edit.html.erb @@ -1,5 +1,7 @@ <%= form_with url: schedule_edit_update_schedules_path, method: :post, class: 'flex flex-col h-full divide-y divide-border-table-border' do %> + <%= hidden_field_tag :controller_id, params[:id] %>
+ <%= @controller.name %> 컨트롤러 @@ -40,13 +42,13 @@ <% end %>
- <%= button_to "초기화", reset_schedules_path, + <%= button_to "초기화", reset_schedule_path(params[:id]), method: :post, data: { turbo_confirm: "정말 초기화하시겠습니까? 모든 스케줄 데이터가 삭제됩니다." }, class: "btn bg-danger" %>
- <%= button_to "추가하기", open_modals_path(type: "add_schedule"), + <%= button_to "추가하기", open_modals_path(type: "add_schedule", id: params[:id]), class: "btn bg-default-slate", data: { turbo_method: :post, diff --git a/app/views/schedules/view.html.erb b/app/views/schedules/view.html.erb new file mode 100644 index 0000000..65675a8 --- /dev/null +++ b/app/views/schedules/view.html.erb @@ -0,0 +1,28 @@ +
+
+ <%= @controller.name %> 컨트롤러 +
+ + + + + + + + + + <% @schedule.each do |s| %> + + + + + + + <% end %> + +
시간사용여부온도
<%= s.hour %>시<%= s.minute %>분<%= s.is_active %><%= s.temperature %> °C
+
+
+ <%= link_to "수정", schedule_edit_schedule_path(@controller.id), class: "btn bg-default-slate" %> +
+
diff --git a/config/routes.rb b/config/routes.rb index afeff1f..3fa9fc4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,17 +14,13 @@ Rails.application.routes.draw do root "schedules#index" resources :schedules do - collection do - post "reset" + member do + get "view" get "schedule_edit" - post "schedule_edit_update" + post "reset" end - end - - resources :modbus do collection do - post "start" - post "stop" + post "schedule_edit_update" end end diff --git a/db/migrate/20250423005211_create_controllers.rb b/db/migrate/20250416131430_create_controllers.rb similarity index 73% rename from db/migrate/20250423005211_create_controllers.rb rename to db/migrate/20250416131430_create_controllers.rb index c9909e1..fe8652a 100644 --- a/db/migrate/20250423005211_create_controllers.rb +++ b/db/migrate/20250416131430_create_controllers.rb @@ -1,6 +1,9 @@ class CreateControllers < ActiveRecord::Migration[8.0] def change create_table :controllers do |t| + t.string :name + t.integer :station_id + t.timestamps end end diff --git a/db/migrate/20250416131440_create_schedules.rb b/db/migrate/20250416131440_create_schedules.rb index 51df18e..9e4ba27 100644 --- a/db/migrate/20250416131440_create_schedules.rb +++ b/db/migrate/20250416131440_create_schedules.rb @@ -1,6 +1,7 @@ class CreateSchedules < ActiveRecord::Migration[8.0] def change create_table :schedules do |t| + t.references :controller, null: false, foreign_key: true t.integer :hour t.integer :minute t.boolean :is_active @@ -8,6 +9,6 @@ class CreateSchedules < ActiveRecord::Migration[8.0] t.timestamps end - add_index :schedules, [ :hour, :minute ], unique: true + add_index :schedules, [:controller_id, :hour, :minute], unique: true end end diff --git a/db/schema.rb b/db/schema.rb index 0f651a4..4dba5a7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,5 +10,25 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 0) do +ActiveRecord::Schema[8.0].define(version: 2025_04_16_131440) do + create_table "controllers", force: :cascade do |t| + t.string "name" + t.integer "station_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "schedules", force: :cascade do |t| + t.integer "controller_id", null: false + 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 ["controller_id", "hour", "minute"], name: "index_schedules_on_controller_id_and_hour_and_minute", unique: true + t.index ["controller_id"], name: "index_schedules_on_controller_id" + end + + add_foreign_key "schedules", "controllers" end diff --git a/db/seeds.rb b/db/seeds.rb index 953e2e0..8927ab7 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -8,6 +8,10 @@ # MovieGenre.find_or_create_by!(name: genre_name) # end +Controller.create(name: "첫번째", station_id: 7) +Controller.create(name: "두번째", station_id: 8) + (0..23).each do | h | - Schedule.create!(hour: h, minute: 0, is_active: true, temperature: 15.0) + Schedule.create!(controller_id: 1, hour: h, minute: 0, is_active: true, temperature: 15.0) + Schedule.create!(controller_id: 2, hour: h, minute: 0, is_active: true, temperature: 15.0) end diff --git a/on_off.rb b/on_off.rb index 9dcf8e8..9395907 100644 --- a/on_off.rb +++ b/on_off.rb @@ -1,10 +1,11 @@ require "rmodbus" require "ccutrer-serialport" +controller_id = ARGV[0]&.to_i value = ARGV[0]&.to_i ModBus::RTUClient.new("/dev/ttyUSB0", 9600) do |cl| - cl.with_slave(7) do |slave| + cl.with_slave(controller_id) do |slave| regs = slave.holding_registers regs[22] = value sleep 0.1 diff --git a/serial.rb b/serial.rb index 5ea916a..dd9d4a9 100644 --- a/serial.rb +++ b/serial.rb @@ -1,10 +1,11 @@ require "rmodbus" require "ccutrer-serialport" -value = ARGV[0]&.to_i +controller_id = ARGV[0]&.to_i +value = ARGV[1]&.to_i ModBus::RTUClient.new("/dev/ttyUSB0", 9600) do |cl| - cl.with_slave(7) do |slave| + cl.with_slave(controller_id) do |slave| regs = slave.holding_registers regs[2] = value sleep 0.1