lib/artoo/robot_class_methods.rb
module Artoo
# The most important class used by Artoo is Robot. This represents the primary
# interface for interacting with a collection of physical computing capabilities.
#
# This module contains the class-level methods used by Artoo::Robot
class Robot
class << self; attr_accessor :connection_types, :device_types; end
module ClassMethods
attr_accessor :working_code, :use_api, :api_host, :api_port
# Connection to some hardware that has one or more devices via some specific protocol
# @example connection :arduino, :adaptor => :firmata, :port => '/dev/tty.usbmodemxxxxx'
# @param [String] name
# @param [Hash] params
def connection(name, params = {})
@connection_types ||= []
Celluloid::Logger.info "Registering connection '#{name}'..."
@connection_types << {:name => name}.merge(params)
end
# Device that uses a connection to communicate
# @example device :collision_detect, :driver => :switch, :pin => 3
# @param [String] name
# @param [Hash] params
def device(name, params = {})
@device_types ||= []
Celluloid::Logger.info "Registering device '#{name}'..."
@device_types << {:name => name}.merge(params)
end
def name(new_name = false)
@name = new_name if new_name
@name
end
# The work that needs to be performed
# @example
# work do
# every(10.seconds) do
# puts "hello, world"
# end
# end
# @param [block] work
def work(&block)
Celluloid::Logger.info "Preparing work..."
self.working_code = block if block_given?
end
# Activate RESTful api
# Example:
# api :host => '127.0.0.1', :port => '1234'
def api(params = {})
Celluloid::Logger.info "Registering api..."
self.use_api = true
self.api_host = params[:host] || '127.0.0.1'
self.api_port = params[:port] || '4321'
end
# Work can be performed by either:
# an existing instance
# an array of existing instances
# or, a new instance can be created
# @param [Robot] robot
def work!(robot=nil)
prepare_work(robot)
return if is_running?
unless cli?
begin
start_api
Artoo::Master.start_work
begin_working
rescue Interrupt
Celluloid::Logger.info 'Shutting down...'
Artoo::Master.stop_work
# Explicitly exit so busy Processor threads can't block
# process shutdown... taken from Sidekiq, thanks!
exit(0)
end
end
end
# Prepare master robots for work
def prepare_work(robot=nil)
if robot.respond_to?(:work)
robots = [robot]
elsif robot.kind_of?(Array)
robots = robot
else
robots = [self.new]
end
Artoo::Master.assign(robots)
end
def begin_working
self_read, self_write = IO.pipe
setup_interrupt(self_write)
handle_signals(self_read)
end
def setup_interrupt(self_write)
Signal.trap("INT") do
self_write.puts("INT")
end
end
def handle_signals(self_read)
while readable_io = IO.select([self_read])
signal = readable_io.first[0].gets.strip
raise Interrupt
end
end
def start_api
Celluloid::Actor[:api] = Api::Server.new(self.api_host, self.api_port) if self.use_api
end
# @return [Boolean] True if test env
def test?
ENV["ARTOO_TEST"] == 'true'
end
# @return [Boolean] True if cli env
def cli?
ENV["ARTOO_CLI"] == 'true'
end
# @return [Boolean] True if it's running
def is_running?
@@running ||= false
@@running == true
end
def running!
@@running = true
end
def stopped!
@@running = false
end
end
end
end