adammck-rubygsm 0.3.1 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/gsm-modem-band +2 -2
- data/bin/sms +38 -0
- data/lib/rubygsm.rb +11 -0
- data/lib/rubygsm/core.rb +102 -43
- data/lib/rubygsm/errors.rb +6 -2
- data/lib/rubygsm/log.rb +24 -4
- data/lib/rubygsm/msg/incoming.rb +31 -0
- data/lib/rubygsm/msg/outgoing.rb +37 -0
- data/rubygsm.gemspec +8 -4
- metadata +6 -2
data/bin/gsm-modem-band
CHANGED
data/bin/sms
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# vim: noet
|
3
|
+
|
4
|
+
dir = File.dirname(__FILE__)
|
5
|
+
require "#{dir}/../lib/rubygsm.rb"
|
6
|
+
|
7
|
+
|
8
|
+
# expand args (TODO: optparser,
|
9
|
+
# which we need so very badly)
|
10
|
+
# or fail with USAGE message
|
11
|
+
if (ARGV.length == 2)
|
12
|
+
recipient, msg = *ARGV
|
13
|
+
port = :auto
|
14
|
+
|
15
|
+
elsif (ARGV.length == 3)
|
16
|
+
port, recipient, msg = *ARGV
|
17
|
+
|
18
|
+
else
|
19
|
+
puts "Usage: sms [PORT] RECIPIENT MESSAGE"
|
20
|
+
puts "(don't forget to quote the message)"
|
21
|
+
puts
|
22
|
+
puts "Examples:"
|
23
|
+
puts ' sms +13474201234 Hello'
|
24
|
+
puts ' sms /dev/ttyS0 +13474201234 "Hello from RubyGSM"'
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
# initialize the modem, send the sms, and
|
29
|
+
# terminate. currently, rubygsm does a lot
|
30
|
+
# of things that aren't strictly required
|
31
|
+
# to get this done; maybe refactor
|
32
|
+
begin
|
33
|
+
modem = Gsm::Modem.new(port)
|
34
|
+
modem.send_sms!(recipient, msg)
|
35
|
+
|
36
|
+
rescue Gsm::Error => err
|
37
|
+
puts "Error: #{err.desc}"
|
38
|
+
end
|
data/lib/rubygsm.rb
CHANGED
@@ -5,3 +5,14 @@ dir = File.dirname(__FILE__)
|
|
5
5
|
require "#{dir}/rubygsm/core.rb"
|
6
6
|
require "#{dir}/rubygsm/errors.rb"
|
7
7
|
require "#{dir}/rubygsm/log.rb"
|
8
|
+
|
9
|
+
# messages are now passed around
|
10
|
+
# using objects, rather than flat
|
11
|
+
# arguments (from, time, msg, etc)
|
12
|
+
require "#{dir}/rubygsm/msg/incoming.rb"
|
13
|
+
require "#{dir}/rubygsm/msg/outgoing.rb"
|
14
|
+
|
15
|
+
# during development, it's important to EXPLODE
|
16
|
+
# as early as possible when something goes wrong
|
17
|
+
Thread.abort_on_exception = true
|
18
|
+
Thread.current["name"] = "main"
|
data/lib/rubygsm/core.rb
CHANGED
@@ -14,8 +14,8 @@ require "date.rb"
|
|
14
14
|
require "rubygems"
|
15
15
|
require "serialport"
|
16
16
|
|
17
|
-
|
18
|
-
class
|
17
|
+
module Gsm
|
18
|
+
class Modem
|
19
19
|
include Timeout
|
20
20
|
|
21
21
|
|
@@ -23,7 +23,7 @@ class GsmModem
|
|
23
23
|
attr_reader :device, :port
|
24
24
|
|
25
25
|
# call-seq:
|
26
|
-
#
|
26
|
+
# Gsm::Modem.new(port, verbosity=:warn)
|
27
27
|
#
|
28
28
|
# Create a new instance, to initialize and communicate exclusively with a
|
29
29
|
# single modem device via the _port_ (which is usually either /dev/ttyS0
|
@@ -76,12 +76,8 @@ class GsmModem
|
|
76
76
|
# the last part is delivered
|
77
77
|
@multipart = {}
|
78
78
|
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
# initialization message (yes, it's underlined)
|
83
|
-
msg = "RubyGSM Initialized at: #{Time.now}"
|
84
|
-
log msg + "\n" + ("=" * msg.length), :file
|
79
|
+
# start logging to file
|
80
|
+
log_init
|
85
81
|
|
86
82
|
# to store incoming messages
|
87
83
|
# until they're dealt with by
|
@@ -144,8 +140,18 @@ class GsmModem
|
|
144
140
|
# notify the network that we accepted
|
145
141
|
# the incoming message (for read receipt)
|
146
142
|
# BEFORE pushing it to the incoming queue
|
147
|
-
# (to avoid really ugly race condition
|
148
|
-
|
143
|
+
# (to avoid really ugly race condition if
|
144
|
+
# the message is grabbed from the queue
|
145
|
+
# and responded to quickly, before we get
|
146
|
+
# a chance to issue at+cnma)
|
147
|
+
begin
|
148
|
+
command "AT+CNMA"
|
149
|
+
|
150
|
+
# not terribly important if it
|
151
|
+
# fails, even though it shouldn't
|
152
|
+
rescue Gsm::Error
|
153
|
+
log "Receipt acknowledgement (CNMA) was rejected"
|
154
|
+
end
|
149
155
|
|
150
156
|
# we might abort if this is
|
151
157
|
catch :skip_processing do
|
@@ -184,8 +190,8 @@ class GsmModem
|
|
184
190
|
# store the incoming data to be picked up
|
185
191
|
# from the attr_accessor as a tuple (this
|
186
192
|
# is kind of ghetto, and WILL change later)
|
187
|
-
|
188
|
-
@incoming.push
|
193
|
+
sent = parse_incoming_timestamp(timestamp)
|
194
|
+
@incoming.push Gsm::Incoming.new(self, from, sent, msg)
|
189
195
|
end
|
190
196
|
|
191
197
|
# drop the two CMT lines (meta-info and message),
|
@@ -211,7 +217,7 @@ class GsmModem
|
|
211
217
|
# which probably means that it has
|
212
218
|
# crashed or been unplugged
|
213
219
|
rescue Errno::EIO
|
214
|
-
raise
|
220
|
+
raise Gsm::WriteError
|
215
221
|
end
|
216
222
|
end
|
217
223
|
|
@@ -235,7 +241,7 @@ class GsmModem
|
|
235
241
|
|
236
242
|
# die if we couldn't read
|
237
243
|
# (nil signifies an error)
|
238
|
-
raise
|
244
|
+
raise Gsm::ReadError\
|
239
245
|
if char.nil?
|
240
246
|
|
241
247
|
# convert the character to ascii,
|
@@ -346,13 +352,13 @@ class GsmModem
|
|
346
352
|
# some errors contain useful error codes,
|
347
353
|
# so raise a proper error with a description
|
348
354
|
if m = buf.match(/^\+(CM[ES]) ERROR: (\d+)$/)
|
349
|
-
log_then_decr "!! Raising
|
355
|
+
log_then_decr "!! Raising Gsm::Error #{$1} #{$2}"
|
350
356
|
raise Error.new(*m.captures)
|
351
357
|
end
|
352
358
|
|
353
359
|
# some errors are not so useful :|
|
354
360
|
if buf == "ERROR"
|
355
|
-
log_then_decr "!! Raising
|
361
|
+
log_then_decr "!! Raising Gsm::Error"
|
356
362
|
raise Error
|
357
363
|
end
|
358
364
|
|
@@ -380,7 +386,9 @@ class GsmModem
|
|
380
386
|
begin
|
381
387
|
|
382
388
|
# prevent other threads from issuing
|
383
|
-
# commands
|
389
|
+
# commands TO THIS MODDEM while this
|
390
|
+
# block is working. this does not lock
|
391
|
+
# threads, just the gsm device
|
384
392
|
if @locked_to and (@locked_to != Thread.current)
|
385
393
|
log "Locked by #{@locked_to["name"]}, waiting..."
|
386
394
|
|
@@ -404,7 +412,7 @@ class GsmModem
|
|
404
412
|
|
405
413
|
# something went bang, which happens, but
|
406
414
|
# just pass it on (after unlocking...)
|
407
|
-
rescue
|
415
|
+
rescue Gsm::Error
|
408
416
|
raise
|
409
417
|
|
410
418
|
|
@@ -514,10 +522,10 @@ class GsmModem
|
|
514
522
|
# Sets the band currently selected for use
|
515
523
|
# by the modem, using either a literal band
|
516
524
|
# number (passed directly to the modem, see
|
517
|
-
#
|
518
|
-
#
|
525
|
+
# Gsm::Modem.Bands) or a named area from
|
526
|
+
# Gsm::Modem.BandAreas:
|
519
527
|
#
|
520
|
-
# m =
|
528
|
+
# m = Gsm::Modem.new
|
521
529
|
# m.band = :usa => "850/1900"
|
522
530
|
# m.band = :africa => "900E/1800"
|
523
531
|
# m.band = :monkey => ArgumentError
|
@@ -526,7 +534,7 @@ class GsmModem
|
|
526
534
|
# America is wearing its ass backwards.)
|
527
535
|
#
|
528
536
|
# Raises ArgumentError if an unrecognized band was
|
529
|
-
# given, or raises
|
537
|
+
# given, or raises Gsm::Error if the modem does
|
530
538
|
# not support the given band.
|
531
539
|
def band=(new_band)
|
532
540
|
|
@@ -548,7 +556,7 @@ class GsmModem
|
|
548
556
|
|
549
557
|
# set the band right now (second wmbs
|
550
558
|
# argument is: 0=NEXT-BOOT, 1=NOW). if it
|
551
|
-
# fails,
|
559
|
+
# fails, allow Gsm::Error to propagate
|
552
560
|
command("AT+WMBS=#{new_band},1")
|
553
561
|
end
|
554
562
|
|
@@ -576,7 +584,7 @@ class GsmModem
|
|
576
584
|
|
577
585
|
# if the command failed, then
|
578
586
|
# the pin was not accepted
|
579
|
-
rescue
|
587
|
+
rescue Gsm::Error
|
580
588
|
return false
|
581
589
|
end
|
582
590
|
end
|
@@ -631,24 +639,70 @@ class GsmModem
|
|
631
639
|
|
632
640
|
|
633
641
|
# call-seq:
|
634
|
-
#
|
642
|
+
# send_sms(message) => true or false
|
643
|
+
# send_sms(recipient, text) => true or false
|
644
|
+
#
|
645
|
+
# Sends an SMS message via _send_sms!_, but traps
|
646
|
+
# any exceptions raised, and returns false instead.
|
647
|
+
# Use this when you don't really care if the message
|
648
|
+
# was sent, which is... never.
|
649
|
+
def send_sms(*args)
|
650
|
+
begin
|
651
|
+
send_sms!(*args)
|
652
|
+
return true
|
653
|
+
|
654
|
+
# something went wrong
|
655
|
+
rescue Gsm::Error
|
656
|
+
return false
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
|
661
|
+
# call-seq:
|
662
|
+
# send_sms!(message) => true or raises Gsm::Error
|
663
|
+
# send_sms!(receipt, text) => true or raises Gsm::Error
|
635
664
|
#
|
636
665
|
# Sends an SMS message, and returns true if the network
|
637
666
|
# accepted it for delivery. We currently can't handle read
|
638
|
-
# receipts, so have no way of confirming delivery.
|
667
|
+
# receipts, so have no way of confirming delivery. If the
|
668
|
+
# device or network rejects the message, a Gsm::Error is
|
669
|
+
# raised containing (hopefully) information about what went
|
670
|
+
# wrong.
|
639
671
|
#
|
640
672
|
# Note: the recipient is passed directly to the modem, which
|
641
673
|
# in turn passes it straight to the SMSC (sms message center).
|
642
|
-
#
|
674
|
+
# For maximum compatibility, use phone numbers in international
|
643
675
|
# format, including the *plus* and *country code*.
|
644
|
-
def
|
676
|
+
def send_sms!(*args)
|
677
|
+
|
678
|
+
# extract values from Outgoing object.
|
679
|
+
# for now, this does not offer anything
|
680
|
+
# in addition to the recipient/text pair,
|
681
|
+
# but provides an upgrade path for future
|
682
|
+
# features (like FLASH and VALIDITY TIME)
|
683
|
+
if args.length == 1\
|
684
|
+
and args[0].is_a? Gsm::Outgoing
|
685
|
+
to = args[0].recipient
|
686
|
+
msg = args[0].text
|
687
|
+
|
688
|
+
# the < v0.4 arguments. maybe
|
689
|
+
# deprecate this one day
|
690
|
+
elsif args.length == 2
|
691
|
+
to, msg = *args
|
692
|
+
|
693
|
+
else
|
694
|
+
raise ArgumentError,\
|
695
|
+
"The Gsm::Modem#send_sms method accepts" +\
|
696
|
+
"a single Gsm::Outgoing instance, " +\
|
697
|
+
"or recipient and text strings"
|
698
|
+
end
|
645
699
|
|
646
700
|
# the number must be in the international
|
647
701
|
# format for some SMSCs (notably, the one
|
648
702
|
# i'm on right now) so maybe add a PLUS
|
649
703
|
#to = "+#{to}" unless(to[0,1]=="+")
|
650
704
|
|
651
|
-
# 1..9 is a special number which does
|
705
|
+
# 1..9 is a special number which does notm
|
652
706
|
# result in a real sms being sent (see inject.rb)
|
653
707
|
if to == "+123456789"
|
654
708
|
log "Not sending test message: #{msg}"
|
@@ -677,12 +731,16 @@ class GsmModem
|
|
677
731
|
# an escpae, to... escape
|
678
732
|
rescue Exception, Timeout::Error => err
|
679
733
|
log "Rescued #{err.desc}"
|
680
|
-
|
681
|
-
|
682
|
-
#
|
734
|
+
write 27.chr
|
735
|
+
|
736
|
+
# allow the error to propagate,
|
737
|
+
# so the application can catch
|
738
|
+
# it for more useful info
|
739
|
+
raise
|
740
|
+
|
741
|
+
ensure
|
742
|
+
log_decr
|
683
743
|
end
|
684
|
-
|
685
|
-
log_decr
|
686
744
|
end
|
687
745
|
|
688
746
|
# if no error was raised,
|
@@ -699,16 +757,16 @@ class GsmModem
|
|
699
757
|
# for each.
|
700
758
|
#
|
701
759
|
# class Receiver
|
702
|
-
# def incoming(
|
703
|
-
# puts "From #{
|
760
|
+
# def incoming(msg)
|
761
|
+
# puts "From #{msg.from} at #{msg.sent}:", msg.text
|
704
762
|
# end
|
705
763
|
# end
|
706
764
|
#
|
707
765
|
# # create the instances,
|
708
766
|
# # and start receiving
|
709
767
|
# rcv = Receiver.new
|
710
|
-
# m =
|
711
|
-
# m.receive
|
768
|
+
# m = Gsm::Modem.new "/dev/ttyS0"
|
769
|
+
# m.receive rcv.method :incoming
|
712
770
|
#
|
713
771
|
# # block until ctrl+c
|
714
772
|
# while(true) { sleep 2 }
|
@@ -738,10 +796,10 @@ class GsmModem
|
|
738
796
|
# in the same format that they were built
|
739
797
|
# back in _parse_incoming_sms!_
|
740
798
|
unless @incoming.empty?
|
741
|
-
@incoming.each do |
|
799
|
+
@incoming.each do |msg|
|
742
800
|
begin
|
743
|
-
callback.call
|
744
|
-
|
801
|
+
callback.call(msg)
|
802
|
+
|
745
803
|
rescue StandardError => err
|
746
804
|
log "Error in callback: #{err}"
|
747
805
|
end
|
@@ -764,4 +822,5 @@ class GsmModem
|
|
764
822
|
# threaded (like debugging handsets)
|
765
823
|
@thr.join if join_thread
|
766
824
|
end
|
767
|
-
end
|
825
|
+
end # Modem
|
826
|
+
end # Gsm
|
data/lib/rubygsm/errors.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# vim: noet
|
5
5
|
#++
|
6
6
|
|
7
|
-
|
7
|
+
module Gsm
|
8
8
|
class Error < StandardError
|
9
9
|
ERRORS = {
|
10
10
|
"CME" => {
|
@@ -94,7 +94,11 @@ class GsmModem
|
|
94
94
|
"[type=#{@type}] [code=#{code}]"
|
95
95
|
end
|
96
96
|
|
97
|
-
alias :to_s :desc
|
97
|
+
# not the same as alias :to_s, :desc,
|
98
|
+
# because this works on subclasses
|
99
|
+
def to_s
|
100
|
+
desc
|
101
|
+
end
|
98
102
|
end
|
99
103
|
|
100
104
|
# TODO: what the hell is going on with
|
data/lib/rubygsm/log.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# vim: noet
|
3
3
|
|
4
|
-
|
4
|
+
module Gsm
|
5
|
+
class Modem
|
5
6
|
private
|
6
7
|
|
7
|
-
# Symbols accepted by the
|
8
|
+
# Symbols accepted by the Gsm::Modem.new _verbosity_
|
8
9
|
# argument. Each level includes all of the levels
|
9
10
|
# below it (ie. :debug includes all :warn messages)
|
10
11
|
LOG_LEVELS = {
|
@@ -14,6 +15,25 @@ class GsmModem
|
|
14
15
|
:warn => 2,
|
15
16
|
:error => 1 }
|
16
17
|
|
18
|
+
def log_init
|
19
|
+
|
20
|
+
fn_port = File.basename(@port)
|
21
|
+
fn_time = Time.now.strftime("%Y-%m-%d.%H-%M-%S")
|
22
|
+
|
23
|
+
# (re-) open the full log file
|
24
|
+
filename = "rubygsm.#{fn_port}.#{fn_time}"
|
25
|
+
@log = File.new filename, "w"
|
26
|
+
|
27
|
+
# dump some useful information
|
28
|
+
# at the top, for debugging
|
29
|
+
log "RUBYGSM"
|
30
|
+
log " port: #{@port}"
|
31
|
+
log " timeout: #{@read_timeout}"
|
32
|
+
log " verbosity: #{@verbosity}"
|
33
|
+
log " started at: #{Time.now}"
|
34
|
+
log "===="
|
35
|
+
end
|
36
|
+
|
17
37
|
def log(msg, level=:debug)
|
18
38
|
ind = " " * (@log_indents[Thread.current] or 0)
|
19
39
|
|
@@ -36,7 +56,6 @@ class GsmModem
|
|
36
56
|
end
|
37
57
|
end
|
38
58
|
|
39
|
-
|
40
59
|
# log a message, and increment future messages
|
41
60
|
# in this thread. useful for nesting logic
|
42
61
|
def log_incr(*args)
|
@@ -56,4 +75,5 @@ class GsmModem
|
|
56
75
|
log(*args)
|
57
76
|
log_decr
|
58
77
|
end
|
59
|
-
end
|
78
|
+
end # Modem
|
79
|
+
end # Gsm
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# vim: noet
|
3
|
+
|
4
|
+
module Gsm
|
5
|
+
class Incoming
|
6
|
+
attr_reader :device, :sender, :sent, :received, :text
|
7
|
+
|
8
|
+
def initialize(device, sender, sent, text)
|
9
|
+
|
10
|
+
# move all arguments into read-only
|
11
|
+
# attributes. ugly, but Struct only
|
12
|
+
# supports read/write attrs
|
13
|
+
@device = device
|
14
|
+
@sender = sender
|
15
|
+
@sent = sent
|
16
|
+
@text = text
|
17
|
+
|
18
|
+
# assume that the message was
|
19
|
+
# received right now, since we
|
20
|
+
# don't have an incoming buffer
|
21
|
+
@received = Time.now
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the sender of this message,
|
25
|
+
# so incoming and outgoing messages
|
26
|
+
# can be logged in the same way.
|
27
|
+
def number
|
28
|
+
sender
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# vim: noet
|
3
|
+
|
4
|
+
module Gsm
|
5
|
+
class Outgoing
|
6
|
+
attr_accessor :recipient, :text
|
7
|
+
attr_reader :device, :sent
|
8
|
+
|
9
|
+
def initialize(device, recipient=nil, text=nil)
|
10
|
+
|
11
|
+
# check that the device is
|
12
|
+
#raise ArgumentError, "Invalid device"\
|
13
|
+
# unless device.respond_to?(:send_sms)
|
14
|
+
|
15
|
+
# init the instance vars
|
16
|
+
@recipient = recipient
|
17
|
+
@device = device
|
18
|
+
@text = text
|
19
|
+
end
|
20
|
+
|
21
|
+
def send!
|
22
|
+
@device.send_sms(self)
|
23
|
+
@sent = Time.now
|
24
|
+
|
25
|
+
# once sent, allow no
|
26
|
+
# more modifications
|
27
|
+
freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the recipient of this message,
|
31
|
+
# so incoming and outgoing messages
|
32
|
+
# can be logged in the same way.
|
33
|
+
def number
|
34
|
+
recipient
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/rubygsm.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "rubygsm"
|
3
|
-
s.version = "0.
|
4
|
-
s.date = "2009-01-
|
3
|
+
s.version = "0.4"
|
4
|
+
s.date = "2009-01-29"
|
5
5
|
s.summary = "Send and receive SMS with a GSM modem"
|
6
6
|
s.email = "adam.mckaig@gmail.com"
|
7
7
|
s.homepage = "http://github.com/adammck/rubygsm"
|
@@ -15,11 +15,15 @@ Gem::Specification.new do |s|
|
|
15
15
|
"lib/rubygsm/core.rb",
|
16
16
|
"lib/rubygsm/errors.rb",
|
17
17
|
"lib/rubygsm/log.rb",
|
18
|
-
"
|
18
|
+
"lib/rubygsm/msg/incoming.rb",
|
19
|
+
"lib/rubygsm/msg/outgoing.rb",
|
20
|
+
"bin/gsm-modem-band",
|
21
|
+
"bin/gsm-app-monitor"
|
19
22
|
]
|
20
23
|
|
21
24
|
s.executables = [
|
22
|
-
"gsm-modem-band"
|
25
|
+
"gsm-modem-band",
|
26
|
+
"sms"
|
23
27
|
]
|
24
28
|
|
25
29
|
s.add_dependency("toholio-serialport", ["> 0.7.1"])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adammck-rubygsm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: "0.4"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Mckaig
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-29 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -25,6 +25,7 @@ description:
|
|
25
25
|
email: adam.mckaig@gmail.com
|
26
26
|
executables:
|
27
27
|
- gsm-modem-band
|
28
|
+
- sms
|
28
29
|
extensions: []
|
29
30
|
|
30
31
|
extra_rdoc_files: []
|
@@ -36,7 +37,10 @@ files:
|
|
36
37
|
- lib/rubygsm/core.rb
|
37
38
|
- lib/rubygsm/errors.rb
|
38
39
|
- lib/rubygsm/log.rb
|
40
|
+
- lib/rubygsm/msg/incoming.rb
|
41
|
+
- lib/rubygsm/msg/outgoing.rb
|
39
42
|
- bin/gsm-modem-band
|
43
|
+
- bin/gsm-app-monitor
|
40
44
|
has_rdoc: true
|
41
45
|
homepage: http://github.com/adammck/rubygsm
|
42
46
|
post_install_message:
|