Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added band switching, and automatic device detection

  • Loading branch information...
commit 30657f6081c60eda8bd65a3fd2ec9933a3de7750 1 parent 6511e53
@adammck authored
View
4 README.rdoc
@@ -3,7 +3,6 @@ to provide a nifty interface to send and receive SMS messages via a GSM modem.
=== Sample Usage
- # included in bin/gsm-app-reverse
class ReverseApp
def initialize(gsm)
@@ -16,7 +15,7 @@ to provide a nifty interface to send and receive SMS messages via a GSM modem.
end
end
- gsm = GsmModem.new("/dev/ttyS0")
+ gsm = GsmModem.new
ReverseApp.new(gsm)
@@ -32,6 +31,7 @@ dependancy, so to install both:
$ sudo gem install adammck-rubygsm
+
==== For Debian/Ubuntu users...
The ruby-serialport library is available in the APT repository as a binary package, which
is substatially less hassle to install than the Gem, for those who don't have a compiler
View
49 bin/gsm-modem-band
@@ -0,0 +1,49 @@
+#!/usr/bin/env ruby
+# vim: noet
+
+#require "rubygems"
+#require "rubygsm"
+dir = File.dirname(__FILE__)
+require "#{dir}/../lib/rubygsm.rb"
+
+
+begin
+ modem = GsmModem.new
+
+rescue GsmModem::Error => err
+ puts "Initialization Error:"
+ puts " " + err.desc
+ exit
+end
+
+
+puts "Found modem on port:"
+puts " " + modem.port
+puts
+
+
+puts "GSM bands supported:"
+puts " " + modem.bands_available.join(", ")
+puts
+
+
+puts "Currently selected:"
+puts " " + modem.band
+puts
+
+
+if ARGV[0]
+ new_band = ARGV[0].downcase
+
+ begin
+ modem.band = new_band
+ puts "Switched to: "
+ puts " " + modem.band
+
+ rescue StandardError => err
+ puts "Error switching band: "
+ puts " " + err
+ end
+
+ puts
+end
View
7 lib/rubygsm.rb
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby
# vim: noet
-require "rubygsm/core.rb"
-require "rubygsm/errors.rb"
-require "rubygsm/lib.rb"
+dir = File.dirname(__FILE__)
+require "#{dir}/rubygsm/core.rb"
+require "#{dir}/rubygsm/errors.rb"
+require "#{dir}/rubygsm/log.rb"
View
110 lib/rubygsm/core.rb
@@ -20,7 +20,7 @@ class GsmModem
attr_accessor :verbosity, :read_timeout
- attr_reader :device
+ attr_reader :device, :port
# call-seq:
# GsmModem.new(port, verbosity=:warn)
@@ -28,10 +28,39 @@ class GsmModem
# Create a new instance, to initialize and communicate exclusively with a
# single modem device via the _port_ (which is usually either /dev/ttyS0
# or /dev/ttyUSB0), and start logging to *rubygsm.log* in the chdir.
- def initialize(port, verbosity=:warn, baud=9600, cmd_delay=0.1)
+ def initialize(port=:auto, verbosity=:warn, baud=9600, cmd_delay=0.1)
+
+ # if no port was specified, we'll attempt to iterate
+ # all of the serial ports that i've ever seen gsm
+ # modems mounted on. this is kind of shaky, and
+ # only works well with a single modem. for now,
+ # we'll try: ttyS0, ttyUSB0, ttyACM0, ttyS1...
+ if port == :auto
+ @device, @port = catch(:found) do
+ 0.upto(8).each do |n|
+ ["ttyS", "ttyUSB", "ttyACM"].each do |prefix|
+ try_port = "/dev/#{prefix}#{n}"
+
+ begin
+ # serialport args: port, baud, data bits, stop bits, parity
+ device = SerialPort.new(try_port, baud, 8, 1, SerialPort::NONE)
+ throw :found, [device, try_port]
+
+ rescue ArgumentError, Errno::ENOENT
+ # do nothing, just continue to
+ # try the next port in order
+ end
+ end
+ end
- # port, baud, data bits, stop bits, parity
- @device = SerialPort.new(port, baud, 8, 1, SerialPort::NONE)
+ # tried all ports, nothing worked
+ raise AutoDetectError
+ end
+
+ else
+ @device = SerialPort.new(port, baud, 8, 1, SerialPort::NONE)
+ @port = port
+ end
@cmd_delay = cmd_delay
@verbosity = verbosity
@@ -419,21 +448,21 @@ def hardware
# command, mapped to frequency bands, in MHz. Copied
# directly from the MultiTech AT command-set reference
Bands = {
- "0" => "850",
- "1" => "900",
- "2" => "1800",
- "3" => "1900",
- "4" => "850/1900",
- "5" => "900E/1800",
- "6" => "900E/1900"
+ 0 => "850",
+ 1 => "900",
+ 2 => "1800",
+ 3 => "1900",
+ 4 => "850/1900",
+ 5 => "900E/1800",
+ 6 => "900E/1900"
}
# call-seq:
- # compatible_bands => array
+ # bands_available => array
#
# Returns an array containing the bands supported by
# the modem.
- def compatible_bands
+ def bands_available
data = query("AT+WMBS=?")
# wmbs data is returned as something like:
@@ -444,7 +473,7 @@ def compatible_bands
# readable description
if m = data.match(/^\+WMBS: \(([\d,]+)\),/)
return m.captures[0].split(",").collect do |index|
- Bands[index]
+ Bands[index.to_i]
end
else
@@ -462,7 +491,7 @@ def compatible_bands
def band
data = query("AT+WMBS?")
if m = data.match(/^\+WMBS: (\d+),/)
- return Bands[m.captures[0]]
+ return Bands[m.captures[0].to_i]
else
# Todo: Recover from this exception
@@ -471,6 +500,57 @@ def band
end
end
+ BandAreas = {
+ :usa => 4,
+ :africa => 5,
+ :europe => 5,
+ :asia => 5,
+ :mideast => 5
+ }
+
+ # call-seq:
+ # band=(_numeric_band_) => string
+ #
+ # 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:
+ #
+ # m = GsmModem.new
+ # m.band = :usa => "850/1900"
+ # m.band = :africa => "900E/1800"
+ # m.band = :monkey => ArgumentError
+ #
+ # (Note that as usual, the United States of
+ # America is wearing its ass backwards.)
+ #
+ # Raises ArgumentError if an unrecognized band was
+ # given, or raises GsmModem::Error if the modem does
+ # not support the given band.
+ def band=(new_band)
+
+ # resolve named bands into numeric
+ # (mhz values first, then band areas)
+ unless new_band.is_a?(Numeric)
+
+ if Bands.has_value?(new_band.to_s)
+ new_band = Bands.index(new_band.to_s)
+
+ elsif BandAreas.has_key?(new_band.to_sym)
+ new_band = BandAreas[new_band.to_sym]
+
+ else
+ err = "Invalid band: #{new_band}"
+ raise ArgumentError.new(err)
+ end
+ end
+
+ # set the band right now (second wmbs
+ # argument is: 0=NEXT-BOOT, 1=NOW). if it
+ # fails, allowGsmModem::Error to propagate
+ command("AT+WMBS=#{new_band},1")
+ end
# call-seq:
# pin_required? => true or false
View
13 lib/rubygsm/errors.rb
@@ -93,11 +93,16 @@ def desc
return "Unknown error (unrecognized command?) " +\
"[type=#{@type}] [code=#{code}]"
end
+
+ alias :to_s :desc
end
+ # TODO: what the hell is going on with
+ # all these "desc" methods? refactor this
+
class TimeoutError < Error #:nodoc:
def desc
- return "The command timed out"
+ "The command timed out"
end
end
@@ -114,4 +119,10 @@ def desc
"may have crashed or been unplugged"
end
end
+
+ class AutoDetectError < Error #:nodoc:
+ def desc
+ "No modem could be auto-detected."
+ end
+ end
end
View
11 rubygsm.gemspec
@@ -1,7 +1,7 @@
Gem::Specification.new do |s|
s.name = "rubygsm"
- s.version = "0.2"
- s.date = "2008-12-18"
+ s.version = "0.3"
+ s.date = "2008-12-31"
s.summary = "Send and receive SMS with a GSM modem"
s.email = "adam.mckaig@gmail.com"
s.homepage = "http://github.com/adammck/rubygsm"
@@ -14,7 +14,12 @@ Gem::Specification.new do |s|
"lib/rubygsm.rb",
"lib/rubygsm/core.rb",
"lib/rubygsm/errors.rb",
- "lib/rubygsm/log.rb"
+ "lib/rubygsm/log.rb",
+ "bin/gsm-modem-band"
+ ]
+
+ s.executables = [
+ "gsm-modem-band"
]
s.add_dependency("toholio-serialport", ["> 0.7.1"])
Please sign in to comment.
Something went wrong with that request. Please try again.