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.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"
end

View File

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

View File

@ -1,69 +1,92 @@
module Biju
class Hayes
attr_accessor :command, :attributes, :ok
attr_reader :answer
attr_reader :modem
#def method_missing(m, *args, &block)
#end
def initialize(port, options = {})
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
at_command { |response| response =~ /OK/ }
#at_command { |response| true }
at_command[:status]
end
def init_modem
at_command('Z') { |response| response =~ /OK/ }
at_command('Z')[:status]
end
def text_mode(enabled = true)
at_command('+CMGF', enabled) { |response| response =~ /OK/ }
at_command('+CMGF', enabled)[:status]
end
def prefered_storage?
at_command('+CPMS') { |response| response =~ /OK/ }
def extended_error(enabled = true)
at_command('+CMEE', enabled)[:status]
end
def answer=(ret)
@answer = ret
ok?
def prefered_storage(pms = nil)
result = at_command('+CPMS', pms)
return result[:array] if result[:cmd] == '+CPMS'
nil
end
def ok?
ok.nil? ? true : !ok.call(answer).nil?
def unlock_pin(pin)
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
private
def at_command(cmd = nil, *args, &block)
option_prefix = nil #options[:prefix] || nil
cmd_root = ['AT', cmd].compact.join(option_prefix)
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
def write(text)
modem.write(text)
hayes_to_obj(modem.wait_answer)
end
def hayes_to_obj(str)
end
# 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/ }
ATTransform.new.apply(ATParser.new.parse(str))
end
end
end

View File

@ -1,36 +1,19 @@
require 'serialport'
require_relative 'sms'
module Biju
class Modem
DEFAULT_OPTIONS = { baud: 9600, data_bits: 8,
stop_bits: 1, parity: SerialPort::NONE }
attr_reader :connection
# @param [Hash] Options to serial connection.
# @option options [String] :port The modem port to connect
#
# Biju::Modem.new(:port => '/dev/ttyUSB0')
# Biju::Modem.new('/dev/ttyUSB0')
#
def initialize(options={}, &block)
raise Exception.new("Port is required") unless options[:port]
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
def initialize(port, options = {})
@connection = SerialPort.new(port, DEFAULT_OPTIONS.merge!(options))
end
# Close the serial connection.
@ -38,59 +21,16 @@ module Biju
connection.close
end
# Return an Array of Sms if there is messages nad return nil if not.
def messages(which = "ALL")
# 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) }
def write(text)
connection.write(text + "\r")
end
# Delete a sms message by id.
# @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
def wait_answer
buffer = ''
while IO.select([connection], [], [], 0.25)
chr = connection.getc.chr;
buffer += chr
buffer << connection.getc.chr
end
puts "RECEIVING : #{buffer}"
buffer
end
end