Skip to content

Commit

Permalink
moved GsmModem to Gsm::Modem, and started passing around message
Browse files Browse the repository at this point in the history
objects, rather than strings. still a bit shaky
  • Loading branch information
adammck committed Jan 12, 2009
1 parent d55c529 commit dc2f422
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 34 deletions.
4 changes: 2 additions & 2 deletions bin/gsm-modem-band
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ require "#{dir}/../lib/rubygsm.rb"


begin
modem = GsmModem.new
modem = Gsm::Modem.new

rescue GsmModem::Error => err
rescue Gsm::Modem::Error => err
puts "Initialization Error:"
puts " " + err.desc
exit
Expand Down
11 changes: 11 additions & 0 deletions lib/rubygsm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@
require "#{dir}/rubygsm/core.rb"
require "#{dir}/rubygsm/errors.rb"
require "#{dir}/rubygsm/log.rb"

# messages are now passed around
# using objects, rather than flat
# arguments (from, time, msg, etc)
require "#{dir}/rubygsm/msg/incoming.rb"
require "#{dir}/rubygsm/msg/outgoing.rb"

# during development, it's important to EXPLODE
# as early as possible when something goes wrong
Thread.abort_on_exception = true
Thread.current["name"] = "main"
90 changes: 63 additions & 27 deletions lib/rubygsm/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
require "rubygems"
require "serialport"


class GsmModem
module Gsm
class Modem
include Timeout


attr_accessor :verbosity, :read_timeout
attr_reader :device, :port

# call-seq:
# GsmModem.new(port, verbosity=:warn)
# Gsm::Modem.new(port, verbosity=:warn)
#
# Create a new instance, to initialize and communicate exclusively with a
# single modem device via the _port_ (which is usually either /dev/ttyS0
Expand Down Expand Up @@ -144,8 +144,18 @@ def parse_incoming_sms!(lines)
# notify the network that we accepted
# the incoming message (for read receipt)
# BEFORE pushing it to the incoming queue
# (to avoid really ugly race condition)
command "AT+CNMA"
# (to avoid really ugly race condition if
# the message is grabbed from the queue
# and responded to quickly, before we get
# a chance to issue at+cnma)
begin
command "AT+CNMA"

# not terribly important if it
# fails, even though it shouldn't
rescue Gsm::Error
log "Receipt acknowledgement (CNMA) was rejected"
end

# we might abort if this is
catch :skip_processing do
Expand Down Expand Up @@ -184,8 +194,8 @@ def parse_incoming_sms!(lines)
# store the incoming data to be picked up
# from the attr_accessor as a tuple (this
# is kind of ghetto, and WILL change later)
dt = parse_incoming_timestamp(timestamp)
@incoming.push [from, dt, msg]
sent = parse_incoming_timestamp(timestamp)
@incoming.push Gsm::Incoming.new(self, from, sent, msg)
end

# drop the two CMT lines (meta-info and message),
Expand All @@ -211,7 +221,7 @@ def write(str)
# which probably means that it has
# crashed or been unplugged
rescue Errno::EIO
raise GsmModem::WriteError
raise Gsm::WriteError
end
end

Expand All @@ -235,7 +245,7 @@ def read(term=nil)

# die if we couldn't read
# (nil signifies an error)
raise GsmModem::ReadError\
raise Gsm::ReadError\
if char.nil?

# convert the character to ascii,
Expand Down Expand Up @@ -346,13 +356,13 @@ def wait(term=nil)
# some errors contain useful error codes,
# so raise a proper error with a description
if m = buf.match(/^\+(CM[ES]) ERROR: (\d+)$/)
log_then_decr "!! Raising GsmModem::Error #{$1} #{$2}"
log_then_decr "!! Raising Gsm::Error #{$1} #{$2}"
raise Error.new(*m.captures)
end

# some errors are not so useful :|
if buf == "ERROR"
log_then_decr "!! Raising GsmModem::Error"
log_then_decr "!! Raising Gsm::Error"
raise Error
end

Expand Down Expand Up @@ -380,7 +390,9 @@ def exclusive &blk
begin

# prevent other threads from issuing
# commands while this block is working
# commands TO THIS MODDEM while this
# block is working. this does not lock
# threads, just the gsm device
if @locked_to and (@locked_to != Thread.current)
log "Locked by #{@locked_to["name"]}, waiting..."

Expand All @@ -404,7 +416,7 @@ def exclusive &blk

# something went bang, which happens, but
# just pass it on (after unlocking...)
rescue GsmModem::Error
rescue Gsm::Error
raise


Expand Down Expand Up @@ -514,10 +526,10 @@ def band
# Sets the band currently selected for use
# by the modem, using either a literal band
# number (passed directly to the modem, see
# GsmModem.Bands) or a named area from
# GsmModem.BandAreas:
# Gsm::Modem.Bands) or a named area from
# Gsm::Modem.BandAreas:
#
# m = GsmModem.new
# m = Gsm::Modem.new
# m.band = :usa => "850/1900"
# m.band = :africa => "900E/1800"
# m.band = :monkey => ArgumentError
Expand All @@ -526,7 +538,7 @@ def band
# America is wearing its ass backwards.)
#
# Raises ArgumentError if an unrecognized band was
# given, or raises GsmModem::Error if the modem does
# given, or raises Gsm::Error if the modem does
# not support the given band.
def band=(new_band)

Expand All @@ -548,7 +560,7 @@ def band=(new_band)

# set the band right now (second wmbs
# argument is: 0=NEXT-BOOT, 1=NOW). if it
# fails, allowGsmModem::Error to propagate
# fails, allow Gsm::Error to propagate
command("AT+WMBS=#{new_band},1")
end

Expand Down Expand Up @@ -576,7 +588,7 @@ def use_pin(pin)

# if the command failed, then
# the pin was not accepted
rescue GsmModem::Error
rescue Gsm::Error
return false
end
end
Expand Down Expand Up @@ -631,7 +643,8 @@ def wait_for_network


# call-seq:
# send(recipient, message) => true or false
# send_sms(message) => true or false
# send_sms(recipient, text) => true or false
#
# Sends an SMS message, and returns true if the network
# accepted it for delivery. We currently can't handle read
Expand All @@ -641,14 +654,36 @@ def wait_for_network
# in turn passes it straight to the SMSC (sms message center).
# for maximum compatibility, use phone numbers in international
# format, including the *plus* and *country code*.
def send(to, msg)
def send_sms(*args)

# extract values from Outgoing object.
# for now, this does not offer anything
# in addition to the recipient/text pair,
# but provides an upgrade path for future
# features (like FLASH and VALIDITY TIME)
if args.length == 1\
and args[0].is_a? Gsm::Outgoing
to = args[0].recipient
msg = args[0].text

# the < v0.4 arguments. maybe
# deprecate this one day
elsif args.length == 2
to, msg = *args

else
raise ArgumentError,\
"The Gsm::Modem#send_sms method accepts" +\
"a single Gsm::Outgoing instance, " +\
"or recipient and text strings"
end

# the number must be in the international
# format for some SMSCs (notably, the one
# i'm on right now) so maybe add a PLUS
#to = "+#{to}" unless(to[0,1]=="+")

# 1..9 is a special number which does not
# 1..9 is a special number which does notm
# result in a real sms being sent (see inject.rb)
if to == "+123456789"
log "Not sending test message: #{msg}"
Expand Down Expand Up @@ -699,16 +734,16 @@ def send(to, msg)
# for each.
#
# class Receiver
# def incoming(caller, datetime, message)
# puts "From #{caller} at #{datetime}:", message
# def incoming(msg)
# puts "From #{msg.from} at #{msg.sent}:", msg.text
# end
# end
#
# # create the instances,
# # and start receiving
# rcv = Receiver.new
# m = GsmModem.new "/dev/ttyS0"
# m.receive inst.method :incoming
# m = Gsm::Modem.new "/dev/ttyS0"
# m.receive rcv.method :incoming
#
# # block until ctrl+c
# while(true) { sleep 2 }
Expand Down Expand Up @@ -764,4 +799,5 @@ def receive(callback, interval=5, join_thread=false)
# threaded (like debugging handsets)
@thr.join if join_thread
end
end
end # Modem
end # Gsm
2 changes: 1 addition & 1 deletion lib/rubygsm/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# vim: noet
#++

class GsmModem
module Gsm
class Error < StandardError
ERRORS = {
"CME" => {
Expand Down
9 changes: 5 additions & 4 deletions lib/rubygsm/log.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#!/usr/bin/env ruby
# vim: noet

class GsmModem
module Gsm
class Modem
private

# Symbols accepted by the GsmModem.new _verbosity_
# Symbols accepted by the Gsm::Modem.new _verbosity_
# argument. Each level includes all of the levels
# below it (ie. :debug includes all :warn messages)
LOG_LEVELS = {
Expand Down Expand Up @@ -36,7 +37,6 @@ def log(msg, level=:debug)
end
end


# log a message, and increment future messages
# in this thread. useful for nesting logic
def log_incr(*args)
Expand All @@ -56,4 +56,5 @@ def log_then_decr(*args)
log(*args)
log_decr
end
end
end # Modem
end # Gsm
28 changes: 28 additions & 0 deletions lib/rubygsm/msg/incoming.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env ruby
# vim: noet

module Gsm
class Incoming
attr_reader :device, :sender, :sent, :received, :text

def initialize(device, sender, sent, text)

# move all arguments into read-only
# attributes. ugly, but Struct only
# supports read/write attrs
@device = device
@sender = sender
@sent = sent
@text = text

# assume that the message was
# received right now, since we
# don't have an incoming buffer
@received = Time.now
end

def to_a
[@device, @sender, @sent, @text]
end
end
end
30 changes: 30 additions & 0 deletions lib/rubygsm/msg/outgoing.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env ruby
# vim: noet

module Gsm
class Outgoing
attr_accessor :recipient, :text
attr_reader :device, :sent

def initialize(device, recipient=nil, text=nil)

# check that the device is
#raise ArgumentError, "Invalid device"\
# unless device.respond_to?(:send_sms)

# init the instance vars
@recipient = recipient
@device = device
@text = text
end

def send!
@device.send_sms(self)
@sent = Time.now

# once sent, allow no
# more modifications
freeze
end
end
end

0 comments on commit dc2f422

Please sign in to comment.