Class: Sms

Inherits:
Object
  • Object
show all
Defined in:
lib/sms.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port) ⇒ Sms

Returns a new instance of Sms.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/sms.rb', line 11

def initialize(port)

  # Create the right device for the platform
  if RUBY_PLATFORM.downcase.include?("mswin")
    @device = Win32::Serial.new(port)
  else  
    @device = Generic::Serial.new(port)
  end  

  raise "Could not open device" unless @device

  # Sometimes commands fail, we count on that
  @max_retry = 5

  # Keep multi-part messages until the last part is delivered
  @multipart = {}

  # Store incoming messages until they're dealt with by someone else
  @messages = []

  # Setup the command for texting and processing
  connect
end

Instance Attribute Details

#ignore_unknown_errorsObject

Returns the value of attribute ignore_unknown_errors.



9
10
11
# File 'lib/sms.rb', line 9

def ignore_unknown_errors
  @ignore_unknown_errors
end

#max_retryObject

Returns the value of attribute max_retry.



9
10
11
# File 'lib/sms.rb', line 9

def max_retry
  @max_retry
end

#messagesObject

Returns the value of attribute messages.



9
10
11
# File 'lib/sms.rb', line 9

def messages
  @messages
end

Instance Method Details

#closeObject



39
40
41
# File 'lib/sms.rb', line 39

def close
  @device = nil
end

#command(data, term = "\r", attempt = 1) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/sms.rb', line 43

def command(data, term = "\r", attempt = 1)
  @device.write(data + "\r")
  response = wait(term)
  response.delete_if do |line|
    (line == data) or
    (line[0,6] == "+WIND:") or
    (line[0,6] == "+CREG:") or
    (line[0,7] == "+CGREG:")
  end
  response
rescue Exception => e
  # Allow retries for device errors or busy errors
  if attempt <= @max_retry and (e.message =~ /\+CMS ERROR/ or e.message =~ /515/)       
    puts "Retrying failed command '#{data}' (#{e.message})"
    sleep(1)
    command "AT+CMGF=1"
    command data, term, attempt + 1
    return
  end
  raise "Error running command '#{data}' (#{e.message})"
end

#encodingObject



75
76
77
# File 'lib/sms.rb', line 75

def encoding
  @encoding
end

#encoding=(enc) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/sms.rb', line 79

def encoding=(enc)
  @encoding = enc
  case enc
    when :ascii
     command "AT+CSCS=\"ASCII\""
    when :utf8
     command "AT+CSCS=\"UTF8\""
    when :ucs2
     command "AT+CSCS=\"UCS2\""
    when :gsm
     command "AT+CSCS=\"GSM\""
    when :iso88591
     command "AT+CSCS=\"8859-1\""
  end
end

#encodings?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/sms.rb', line 71

def encodings?
  command "AT+CSCS=?"
end

#finalizeObject



35
36
37
# File 'lib/sms.rb', line 35

def finalize
  close
end

#hardwareObject



127
128
129
130
131
132
# File 'lib/sms.rb', line 127

def hardware
  {:manufacturer => query("AT+CGMI"),
   :model        => query("AT+CGMM"),
   :revision     => query("AT+CGMR"),
   :serial       => query("AT+CGSN") }
end

#pin=(pin) ⇒ Object



143
144
145
146
# File 'lib/sms.rb', line 143

def pin=(pin)
  return unless pin?
  command "AT+CPIN=#{pin}"
end

#pin?Boolean

Returns:

  • (Boolean)


139
140
141
# File 'lib/sms.rb', line 139

def pin?
  not command("AT+CPIN?").include?("+CPIN: READY")
end

#processObject



134
135
136
137
# File 'lib/sms.rb', line 134

def process 
  @messages = []
  fetch_and_delete_stored_messages
end

#query(data) ⇒ Object



65
66
67
68
69
# File 'lib/sms.rb', line 65

def query(data)
  response = command(data)
  return response[0] if response.size == 2 and response[1] == "OK"
  raise "Invalid response: #{response.inspect}"
end

#signal?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/sms.rb', line 148

def signal?
  query("AT+CSQ")
end

#sms(number, text, attempt = 1) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/sms.rb', line 95

def sms(number, text, attempt = 1)
  puts "Preparing message"
  # Switch to text mode (should already be there, but seems to get reset)
  command "AT+CMGF=1"
  position = nil
  # initiate the sms, and wait for either the text prompt or an error
  command "AT+CMGW=\"#{number}\"", ["\r", "> "]
  begin
    # send the sms, and wait until it is accepted or rejected
    text = encode(text)
    @device.write "#{text}#{26.chr}"
    response = wait
    position = "#{response}".scan(/\+CMGW\:\s*(\d*)/).first
  rescue Exception => e
    # Escape entry mode
    @device.write 27.chr

    # Allow retries for device errors or busy errors
    if attempt <= @max_retry and (e.message =~ /\+CMS ERROR/ or e.message =~ /515/)       
      puts "Retrying failed sms to '#{number}' (#{e.message})"
      sleep(1)
      sms number, text, attempt + 1
      return
    end
    raise
  end
  puts "Sending"
  command "AT+CMGF=1"
  command "AT+CMSS=#{position}" if position
  response
end