Move AT commands in Hayes class and use Modem to send to SerialPort

develop
Guillaume DOTT 2013-09-03 17:02:36 +02:00
parent b1568bbf24
commit 67571dd12e
4 changed files with 83 additions and 118 deletions

View File

@ -15,8 +15,8 @@ Gem::Specification.new do |gem|
gem.require_paths = ["lib"] gem.require_paths = ["lib"]
gem.version = Biju::VERSION gem.version = Biju::VERSION
gem.add_development_dependency "minitest", "3.0.0" gem.add_development_dependency "rspec", "~> 2.14.0"
gem.add_dependency "serialport", ">=1.0.4" gem.add_dependency "serialport", "~> 1.1.0"
gem.add_dependency "parslet", "~> 1.5.0" gem.add_dependency "parslet", "~> 1.5.0"
end end

View File

@ -1,4 +1,6 @@
require 'biju/version' require 'biju/version'
require "biju/modem" require 'biju/modem'
require "biju/sms" require 'biju/to_hayes'
require "biju/hayes" require 'biju/hayes'
require 'biju/sms'
require 'biju/parser'

View File

@ -1,69 +1,92 @@
module Biju module Biju
class Hayes class Hayes
attr_accessor :command, :attributes, :ok attr_reader :modem
attr_reader :answer
#def method_missing(m, *args, &block) def initialize(port, options = {})
#end pin = options.delete(:pin) || '0000'
@modem = Modem.new(port, options)
attention
init_modem
unlock_pin pin
text_mode
extended_error
end
def at_command(cmd = nil, *args, &block)
command = ['AT', cmd].compact.join
command_args = args.compact.to_hayes
full_command = [command, (command_args.empty? ? nil : command_args)]
.compact.join('=')
answer = write(full_command)
return block.call(answer) if block_given?
answer
end
def attention def attention
at_command { |response| response =~ /OK/ } at_command[:status]
#at_command { |response| true }
end end
def init_modem def init_modem
at_command('Z') { |response| response =~ /OK/ } at_command('Z')[:status]
end end
def text_mode(enabled = true) def text_mode(enabled = true)
at_command('+CMGF', enabled) { |response| response =~ /OK/ } at_command('+CMGF', enabled)[:status]
end end
def prefered_storage? def extended_error(enabled = true)
at_command('+CPMS') { |response| response =~ /OK/ } at_command('+CMEE', enabled)[:status]
end end
def answer=(ret) def prefered_storage(pms = nil)
@answer = ret result = at_command('+CPMS', pms)
ok? return result[:array] if result[:cmd] == '+CPMS'
nil
end end
def ok? def unlock_pin(pin)
ok.nil? ? true : !ok.call(answer).nil? at_command('+CPIN', pin)[:status]
end
def messages(which = "ALL")
prefered_storage 'MT'
sms = at_command('+CMGL', which)
return sms[:status] if !sms.has_key?(:sms) || sms[:sms].empty?
sms[:sms].map do |msg|
Biju::Sms.new(
id: msg[:infos][0],
phone_number: msg[:infos][2],
datetime: msg[:infos][4],
message: msg[:message].chomp)
end
end
# Delete a sms message by id.
# @param [Fixnum] Id of sms message on modem.
def delete(id)
at_command('+CMGD', id)
end
def send(sms, options = {})
at_command('+CMGS', sms.phone_number)
write("#{sms.message}#{26.chr}")
end end
private private
def at_command(cmd = nil, *args, &block) def write(text)
option_prefix = nil #options[:prefix] || nil modem.write(text)
cmd_root = ['AT', cmd].compact.join(option_prefix) hayes_to_obj(modem.wait_answer)
cmd_args = args.compact.map { |arg| to_hayes_string(arg) } unless args.empty?
self.command = [cmd_root, cmd_args].compact.join('=')
self.ok = block if block_given?
command
end end
def hayes_to_obj(str) def hayes_to_obj(str)
end ATTransform.new.apply(ATParser.new.parse(str))
# OPTIMIZE : add () to array
def to_hayes_string(arg)
case arg
when String
"\"#{arg}\""
when Array
arg.join(',')
when TrueClass, FalseClass
!!arg ? 1 : 0
else
"?"
end
end
end
class HayesSms < Hayes
def unlock_pin(pin)
at_command("+CPIN=#{to_hayes_string(pin)}") { |response| response =~ /OK/ }
end end
end end
end end

View File

@ -1,36 +1,19 @@
require 'serialport' require 'serialport'
require_relative 'sms'
module Biju module Biju
class Modem class Modem
DEFAULT_OPTIONS = { baud: 9600, data_bits: 8,
stop_bits: 1, parity: SerialPort::NONE }
attr_reader :connection attr_reader :connection
# @param [Hash] Options to serial connection. # @param [Hash] Options to serial connection.
# @option options [String] :port The modem port to connect # @option options [String] :port The modem port to connect
# #
# Biju::Modem.new(:port => '/dev/ttyUSB0') # Biju::Modem.new('/dev/ttyUSB0')
# #
def initialize(options={}, &block) def initialize(port, options = {})
raise Exception.new("Port is required") unless options[:port] @connection = SerialPort.new(port, DEFAULT_OPTIONS.merge!(options))
pin = options[:pin] || '0000'
@connection = connect(options)
cmd("AT")
# initialize modem
cmd("ATZ")
# unlock pin code
cmd("AT+CPIN=\"#{pin}\"") if pin
cmd("AT+CPMS=?")
# set SMS text mode
cmd("AT+CMGF=1")
# set extended error reports
cmd('AT+CMEE=1')
#instance_eval &block if block_given?
if block_given?
yield connection
close
end
end end
# Close the serial connection. # Close the serial connection.
@ -38,59 +21,16 @@ module Biju
connection.close connection.close
end end
# Return an Array of Sms if there is messages nad return nil if not. def write(text)
def messages(which = "ALL") connection.write(text + "\r")
# read message from all storage in the mobile phone (sim+mem)
cmd('AT+CPMS="MT"')
# get message list
sms = cmd('AT+CMGL="%s"' % which )
# collect messages
msgs = sms.scan(/\+CMGL\:\s*?(\d+)\,.*?\,\"(.+?)\"\,.*?\,\"(.+?)\".*?\n(.*)/)
return nil unless msgs
msgs.collect!{ |msg| Biju::Sms.new(:id => msg[0], :phone_number => msg[1], :datetime => msg[2], :message => msg[3].chomp) }
end end
# Delete a sms message by id. def wait_answer
# @param [Fixnum] Id of sms message on modem.
def delete(id)
cmd("AT+CMGD=#{id}")
end
def send(sms, options = {})
# initiate the sms, and wait for either
# the text prompt or an error message
cmd("AT+CMGS=\"#{sms.phone_number}\"")
# send the sms, and wait until
# it is accepted or rejected
cmd("#{sms.message}#{26.chr}")
# ... check reception
end
private
def connect(options)
port = options.delete(:port)
SerialPort.new(port, default_options.merge!(options))
end
def default_options
{ :baud => 9600, :data_bits => 8, :stop_bits => 1, :parity => SerialPort::NONE }
end
def cmd(cmd)
puts "SENDING : #{cmd}"
connection.write(cmd + "\r")
wait_str = wait
#p "#{cmd} --> #{wait_str}"
end
def wait
buffer = '' buffer = ''
while IO.select([connection], [], [], 0.25) while IO.select([connection], [], [], 0.25)
chr = connection.getc.chr; buffer << connection.getc.chr
buffer += chr
end end
puts "RECEIVING : #{buffer}"
buffer buffer
end end
end end