anjlab-ruby-smpp 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGELOG +52 -0
  2. data/CONTRIBUTORS.txt +11 -0
  3. data/Gemfile +8 -0
  4. data/Gemfile.lock +18 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +89 -0
  7. data/Rakefile +53 -0
  8. data/VERSION +1 -0
  9. data/config/environment.rb +2 -0
  10. data/examples/PDU1.example +26 -0
  11. data/examples/PDU2.example +26 -0
  12. data/examples/sample_gateway.rb +137 -0
  13. data/examples/sample_smsc.rb +102 -0
  14. data/lib/smpp.rb +25 -0
  15. data/lib/smpp/base.rb +308 -0
  16. data/lib/smpp/encoding/utf8_encoder.rb +37 -0
  17. data/lib/smpp/optional_parameter.rb +35 -0
  18. data/lib/smpp/pdu/base.rb +183 -0
  19. data/lib/smpp/pdu/bind_base.rb +25 -0
  20. data/lib/smpp/pdu/bind_receiver.rb +4 -0
  21. data/lib/smpp/pdu/bind_receiver_response.rb +4 -0
  22. data/lib/smpp/pdu/bind_resp_base.rb +17 -0
  23. data/lib/smpp/pdu/bind_transceiver.rb +4 -0
  24. data/lib/smpp/pdu/bind_transceiver_response.rb +4 -0
  25. data/lib/smpp/pdu/deliver_sm.rb +142 -0
  26. data/lib/smpp/pdu/deliver_sm_response.rb +12 -0
  27. data/lib/smpp/pdu/enquire_link.rb +11 -0
  28. data/lib/smpp/pdu/enquire_link_response.rb +11 -0
  29. data/lib/smpp/pdu/generic_nack.rb +20 -0
  30. data/lib/smpp/pdu/submit_multi.rb +68 -0
  31. data/lib/smpp/pdu/submit_multi_response.rb +49 -0
  32. data/lib/smpp/pdu/submit_sm.rb +91 -0
  33. data/lib/smpp/pdu/submit_sm_response.rb +31 -0
  34. data/lib/smpp/pdu/unbind.rb +11 -0
  35. data/lib/smpp/pdu/unbind_response.rb +12 -0
  36. data/lib/smpp/receiver.rb +27 -0
  37. data/lib/smpp/server.rb +223 -0
  38. data/lib/smpp/transceiver.rb +109 -0
  39. data/lib/sms.rb +9 -0
  40. data/ruby-smpp.gemspec +96 -0
  41. data/test/delegate.rb +28 -0
  42. data/test/encoding_test.rb +231 -0
  43. data/test/optional_parameter_test.rb +30 -0
  44. data/test/pdu_parsing_test.rb +111 -0
  45. data/test/receiver_test.rb +232 -0
  46. data/test/responsive_delegate.rb +53 -0
  47. data/test/server.rb +56 -0
  48. data/test/smpp_test.rb +239 -0
  49. data/test/submit_sm_test.rb +40 -0
  50. data/test/transceiver_test.rb +35 -0
  51. metadata +133 -0
@@ -0,0 +1,109 @@
1
+ # The SMPP Transceiver maintains a bidirectional connection to an SMSC.
2
+ # Provide a config hash with connection options to get started.
3
+ # See the sample_gateway.rb for examples of config values.
4
+ # The transceiver accepts a delegate object that may implement
5
+ # the following (all optional) methods:
6
+ #
7
+ # mo_received(transceiver, pdu)
8
+ # delivery_report_received(transceiver, pdu)
9
+ # message_accepted(transceiver, mt_message_id, pdu)
10
+ # message_rejected(transceiver, mt_message_id, pdu)
11
+ # bound(transceiver)
12
+ # unbound(transceiver)
13
+
14
+ class Smpp::Transceiver < Smpp::Base
15
+
16
+ # Send an MT SMS message. Delegate will receive message_accepted callback when SMSC
17
+ # acknowledges, or the message_rejected callback upon error
18
+ def send_mt(message_id, source_addr, destination_addr, short_message, options={})
19
+ logger.debug "Sending MT: #{short_message}"
20
+ if @state == :bound
21
+ pdu = Pdu::SubmitSm.new(source_addr, destination_addr, short_message, options)
22
+ write_pdu pdu
23
+
24
+ # keep the message ID so we can associate the SMSC message ID with our message
25
+ # when the response arrives.
26
+ @ack_ids[pdu.sequence_number] = message_id
27
+ else
28
+ raise InvalidStateException, "Transceiver is unbound. Cannot send MT messages."
29
+ end
30
+ end
31
+
32
+ # Send a concatenated message with a body of > 160 characters as multiple messages.
33
+ def send_concat_mt(message_id, source_addr, destination_addr, message, options = {})
34
+ logger.debug "Sending concatenated MT: #{message}"
35
+ if @state == :bound
36
+ # Split the message into parts of 153 characters. (160 - 7 characters for UDH)
37
+ parts = []
38
+ while message.size > 0 do
39
+ parts << message.slice!(0..Smpp::Transceiver.get_message_part_size(options))
40
+ end
41
+
42
+ 0.upto(parts.size-1) do |i|
43
+ udh = sprintf("%c", 5) # UDH is 5 bytes.
44
+ udh << sprintf("%c%c", 0, 3) # This is a concatenated message
45
+
46
+ #TODO Figure out why this needs to be an int here, it's a string elsewhere
47
+ udh << sprintf("%c", message_id) # The ID for the entire concatenated message
48
+
49
+ udh << sprintf("%c", parts.size) # How many parts this message consists of
50
+ udh << sprintf("%c", i+1) # This is part i+1
51
+
52
+ options[:esm_class] = 64 # This message contains a UDH header.
53
+ options[:udh] = udh
54
+
55
+ pdu = Pdu::SubmitSm.new(source_addr, destination_addr, parts[i], options)
56
+ write_pdu pdu
57
+
58
+ # This is definately a bit hacky - multiple PDUs are being associated with a single
59
+ # message_id.
60
+ @ack_ids[pdu.sequence_number] = message_id
61
+ end
62
+ else
63
+ raise InvalidStateException, "Transceiver is unbound. Connot send MT messages."
64
+ end
65
+ end
66
+
67
+ # Send MT SMS message for multiple dest_address
68
+ # Author: Abhishek Parolkar (abhishek[at]parolkar.com)
69
+ # USAGE: $tx.send_multi_mt(123, "9100000000", ["9199000000000","91990000000001","9199000000002"], "Message here")
70
+ def send_multi_mt(message_id, source_addr, destination_addr_arr, short_message, options={})
71
+ logger.debug "Sending Multiple MT: #{short_message}"
72
+ if @state == :bound
73
+ pdu = Pdu::SubmitMulti.new(source_addr, destination_addr_arr, short_message, options)
74
+ write_pdu pdu
75
+
76
+ # keep the message ID so we can associate the SMSC message ID with our message
77
+ # when the response arrives.
78
+ @ack_ids[pdu.sequence_number] = message_id
79
+ else
80
+ raise InvalidStateException, "Transceiver is unbound. Cannot send MT messages."
81
+ end
82
+ end
83
+
84
+ # Send BindTransceiverResponse PDU.
85
+ def send_bind
86
+ raise IOError, 'Receiver already bound.' unless unbound?
87
+ pdu = Pdu::BindTransceiver.new(
88
+ @config[:system_id],
89
+ @config[:password],
90
+ @config[:system_type],
91
+ @config[:source_ton],
92
+ @config[:source_npi],
93
+ @config[:source_address_range])
94
+ write_pdu(pdu)
95
+ end
96
+
97
+ # Use data_coding to find out what message part size we can use
98
+ # http://en.wikipedia.org/wiki/SMS#Message_size
99
+ def self.get_message_part_size options
100
+ return 153 if options[:data_coding].nil?
101
+ return 153 if options[:data_coding] == 0
102
+ return 134 if options[:data_coding] == 3
103
+ return 134 if options[:data_coding] == 5
104
+ return 134 if options[:data_coding] == 6
105
+ return 134 if options[:data_coding] == 7
106
+ return 67 if options[:data_coding] == 8
107
+ return 153
108
+ end
109
+ end
data/lib/sms.rb ADDED
@@ -0,0 +1,9 @@
1
+ # Basic SMS class for sample gateway
2
+
3
+ class Sms
4
+ attr_accessor :id, :from, :to, :body
5
+
6
+ def initialize(body)
7
+ self.body = body
8
+ end
9
+ end
data/ruby-smpp.gemspec ADDED
@@ -0,0 +1,96 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{anjlab-ruby-smpp}
8
+ s.version = "0.6.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ray Krueger", "August Z. Flatby"]
12
+ s.date = %q{2011-10-14}
13
+ s.description = %q{Ruby implementation of the SMPP protocol, based on EventMachine. SMPP is a protocol that allows ordinary people outside the mobile network to exchange SMS messages directly with mobile operators.}
14
+ s.email = %q{raykrueger@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "CHANGELOG",
17
+ "CONTRIBUTORS.txt",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ "CHANGELOG",
22
+ "CONTRIBUTORS.txt",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "config/environment.rb",
30
+ "examples/PDU1.example",
31
+ "examples/PDU2.example",
32
+ "examples/sample_gateway.rb",
33
+ "examples/sample_smsc.rb",
34
+ "lib/smpp.rb",
35
+ "lib/smpp/base.rb",
36
+ "lib/smpp/encoding/utf8_encoder.rb",
37
+ "lib/smpp/optional_parameter.rb",
38
+ "lib/smpp/pdu/base.rb",
39
+ "lib/smpp/pdu/bind_base.rb",
40
+ "lib/smpp/pdu/bind_receiver.rb",
41
+ "lib/smpp/pdu/bind_receiver_response.rb",
42
+ "lib/smpp/pdu/bind_resp_base.rb",
43
+ "lib/smpp/pdu/bind_transceiver.rb",
44
+ "lib/smpp/pdu/bind_transceiver_response.rb",
45
+ "lib/smpp/pdu/deliver_sm.rb",
46
+ "lib/smpp/pdu/deliver_sm_response.rb",
47
+ "lib/smpp/pdu/enquire_link.rb",
48
+ "lib/smpp/pdu/enquire_link_response.rb",
49
+ "lib/smpp/pdu/generic_nack.rb",
50
+ "lib/smpp/pdu/submit_multi.rb",
51
+ "lib/smpp/pdu/submit_multi_response.rb",
52
+ "lib/smpp/pdu/submit_sm.rb",
53
+ "lib/smpp/pdu/submit_sm_response.rb",
54
+ "lib/smpp/pdu/unbind.rb",
55
+ "lib/smpp/pdu/unbind_response.rb",
56
+ "lib/smpp/receiver.rb",
57
+ "lib/smpp/server.rb",
58
+ "lib/smpp/transceiver.rb",
59
+ "lib/sms.rb",
60
+ "ruby-smpp.gemspec",
61
+ "test/delegate.rb",
62
+ "test/encoding_test.rb",
63
+ "test/optional_parameter_test.rb",
64
+ "test/pdu_parsing_test.rb",
65
+ "test/receiver_test.rb",
66
+ "test/responsive_delegate.rb",
67
+ "test/server.rb",
68
+ "test/smpp_test.rb",
69
+ "test/submit_sm_test.rb",
70
+ "test/transceiver_test.rb"
71
+ ]
72
+ s.homepage = %q{http://github.com/raykrueger/ruby-smpp}
73
+ s.require_paths = ["lib"]
74
+ s.rubyforge_project = %q{ruby-smpp}
75
+ s.rubygems_version = %q{1.4.2}
76
+ s.summary = %q{Ruby implementation of the SMPP protocol, based on EventMachine.}
77
+
78
+ if s.respond_to? :specification_version then
79
+ s.specification_version = 3
80
+
81
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
82
+ s.add_runtime_dependency(%q<eventmachine>, [">= 0.10.0"])
83
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
84
+ s.add_development_dependency(%q<rake>, [">= 0"])
85
+ else
86
+ s.add_dependency(%q<eventmachine>, [">= 0.10.0"])
87
+ s.add_dependency(%q<jeweler>, [">= 0"])
88
+ s.add_dependency(%q<rake>, [">= 0"])
89
+ end
90
+ else
91
+ s.add_dependency(%q<eventmachine>, [">= 0.10.0"])
92
+ s.add_dependency(%q<jeweler>, [">= 0"])
93
+ s.add_dependency(%q<rake>, [">= 0"])
94
+ end
95
+ end
96
+
data/test/delegate.rb ADDED
@@ -0,0 +1,28 @@
1
+ # the delagate receives callbacks when interesting things happen on the connection
2
+ class Delegate
3
+
4
+ def mo_received(transceiver, pdu)
5
+ puts "** mo_received"
6
+ end
7
+
8
+ def delivery_report_received(transceiver, pdu)
9
+ puts "** delivery_report_received"
10
+ end
11
+
12
+ def message_accepted(transceiver, mt_message_id, pdu)
13
+ puts "** message_sent"
14
+ end
15
+
16
+ def message_rejected(transceiver, mt_message_id, pdu)
17
+ puts "** message_rejected"
18
+ end
19
+
20
+ def bound(transceiver)
21
+ puts "** bound"
22
+ end
23
+
24
+ def unbound(transceiver)
25
+ puts "** unbound"
26
+ EventMachine::stop_event_loop
27
+ end
28
+ end
@@ -0,0 +1,231 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'smpp/encoding/utf8_encoder'
4
+
5
+ require File.expand_path(File.dirname(__FILE__) + "../../lib/smpp")
6
+
7
+ class EncodingTest < Test::Unit::TestCase
8
+
9
+
10
+ def setup
11
+ ::Smpp::Pdu::DeliverSm.data_encoder = ::Smpp::Encoding::Utf8Encoder.new
12
+ end
13
+
14
+ def teardown
15
+ ::Smpp::Pdu::DeliverSm.data_encoder = nil
16
+ end
17
+
18
+ def test_should_decode_pound_sign_from_hp_roman_8_to_utf_8
19
+ raw_data = <<-EOF
20
+ 0000 003d 0000 0005 0000 0000 0000 0002
21
+ 0001 0134 3437 3830 3330 3239 3833 3700
22
+ 0101 3434 3738 3033 3032 3938 3337 0000
23
+ 0000 0000 0000 0000 2950 6C65 6173 6520
24
+ 6465 706F 7369 7420 BB35 2069 6E74 6F20
25
+ 6D79 2061 6363 6F75 6E74 2C20 4A6F 73C5
26
+ EOF
27
+
28
+ pdu = create_pdu(raw_data)
29
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
30
+ assert_equal 0, pdu.data_coding
31
+
32
+ expected = "Please deposit \302\2435 into my account, Jos\303\251"
33
+ assert_equal expected, pdu.short_message
34
+ end
35
+
36
+ def test_should_unescape_gsm_escaped_euro_symbol
37
+ raw_data = <<-EOF
38
+ 0000 003d 0000 0005 0000 0000 0000 0002
39
+ 0001 0134 3437 3830 3330 3239 3833 3700
40
+ 0101 3434 3738 3033 3032 3938 3337 0000
41
+ 0000 0000 0000 0000 1950 6c65 6173 6520
42
+ 6465 706f 7369 7420 8d65 3520 7468 616e
43
+ 6b73
44
+ EOF
45
+
46
+ pdu = create_pdu(raw_data)
47
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
48
+ assert_equal 0, pdu.data_coding
49
+
50
+ expected = "Please deposit \342\202\2545 thanks"
51
+ assert_equal expected, pdu.short_message
52
+ end
53
+
54
+ def test_should_unescape_gsm_escaped_left_curly_bracket_symbol
55
+ raw_data = <<-EOF
56
+ 0000 003d 0000 0005 0000 0000 0000 0002
57
+ 0001 0134 3437 3830 3330 3239 3833 3700
58
+ 0101 3434 3738 3033 3032 3938 3337 0000
59
+ 0000 0000 0000 0000 028d 28
60
+ EOF
61
+
62
+ pdu = create_pdu(raw_data)
63
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
64
+ assert_equal 0, pdu.data_coding
65
+
66
+ assert_equal "{", pdu.short_message
67
+ end
68
+
69
+ def test_should_unescape_gsm_escaped_right_curly_bracket_symbol
70
+ raw_data = <<-EOF
71
+ 0000 003d 0000 0005 0000 0000 0000 0002
72
+ 0001 0134 3437 3830 3330 3239 3833 3700
73
+ 0101 3434 3738 3033 3032 3938 3337 0000
74
+ 0000 0000 0000 0000 028d 29
75
+ EOF
76
+
77
+ pdu = create_pdu(raw_data)
78
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
79
+ assert_equal 0, pdu.data_coding
80
+
81
+ assert_equal "}", pdu.short_message
82
+ end
83
+
84
+ def test_should_unescape_gsm_escaped_tilde_symbol
85
+ raw_data = <<-EOF
86
+ 0000 003d 0000 0005 0000 0000 0000 0002
87
+ 0001 0134 3437 3830 3330 3239 3833 3700
88
+ 0101 3434 3738 3033 3032 3938 3337 0000
89
+ 0000 0000 0000 0000 028d 3d
90
+ EOF
91
+
92
+ pdu = create_pdu(raw_data)
93
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
94
+ assert_equal 0, pdu.data_coding
95
+
96
+ assert_equal "~", pdu.short_message
97
+ end
98
+
99
+ def test_should_unescape_gsm_escaped_left_square_bracket_symbol
100
+ raw_data = <<-EOF
101
+ 0000 003d 0000 0005 0000 0000 0000 0002
102
+ 0001 0134 3437 3830 3330 3239 3833 3700
103
+ 0101 3434 3738 3033 3032 3938 3337 0000
104
+ 0000 0000 0000 0000 028d 3c
105
+ EOF
106
+
107
+ pdu = create_pdu(raw_data)
108
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
109
+ assert_equal 0, pdu.data_coding
110
+
111
+ assert_equal "[", pdu.short_message
112
+ end
113
+
114
+ def test_should_unescape_gsm_escaped_right_square_bracket_symbol
115
+ raw_data = <<-EOF
116
+ 0000 003d 0000 0005 0000 0000 0000 0002
117
+ 0001 0134 3437 3830 3330 3239 3833 3700
118
+ 0101 3434 3738 3033 3032 3938 3337 0000
119
+ 0000 0000 0000 0000 028d 3e
120
+ EOF
121
+
122
+ pdu = create_pdu(raw_data)
123
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
124
+ assert_equal 0, pdu.data_coding
125
+
126
+ assert_equal "]", pdu.short_message
127
+ end
128
+
129
+ def test_should_unescape_gsm_escaped_backslash_symbol
130
+ raw_data = <<-EOF
131
+ 0000 003d 0000 0005 0000 0000 0000 0002
132
+ 0001 0134 3437 3830 3330 3239 3833 3700
133
+ 0101 3434 3738 3033 3032 3938 3337 0000
134
+ 0000 0000 0000 0000 028d 2f
135
+ EOF
136
+
137
+ pdu = create_pdu(raw_data)
138
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
139
+ assert_equal 0, pdu.data_coding
140
+
141
+ assert_equal "\\", pdu.short_message
142
+ end
143
+
144
+ def test_should_unescape_gsm_escaped_vertical_bar_symbol
145
+ raw_data = <<-EOF
146
+ 0000 003d 0000 0005 0000 0000 0000 0002
147
+ 0001 0134 3437 3830 3330 3239 3833 3700
148
+ 0101 3434 3738 3033 3032 3938 3337 0000
149
+ 0000 0000 0000 0000 028d b8
150
+ EOF
151
+
152
+ pdu = create_pdu(raw_data)
153
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
154
+ assert_equal 0, pdu.data_coding
155
+
156
+ assert_equal "|", pdu.short_message
157
+ end
158
+
159
+ def test_should_unescape_gsm_escaped_caret_or_circumflex_symbol
160
+ raw_data = <<-EOF
161
+ 0000 003d 0000 0005 0000 0000 0000 0002
162
+ 0001 0134 3437 3830 3330 3239 3833 3700
163
+ 0101 3434 3738 3033 3032 3938 3337 0000
164
+ 0000 0000 0000 0000 028d 86
165
+ EOF
166
+
167
+ pdu = create_pdu(raw_data)
168
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
169
+ assert_equal 0, pdu.data_coding
170
+
171
+ expected = "\313\206"
172
+ assert_equal expected, pdu.short_message
173
+ end
174
+
175
+ def test_should_unescape_gsm_escaped_characters_together
176
+ raw_data = <<-EOF
177
+ 0000 003d 0000 0005 0000 0000 0000 0002
178
+ 0001 0134 3437 3830 3330 3239 3833 3700
179
+ 0101 3434 3738 3033 3032 3938 3337 0000
180
+ 0000 0000 0000 0000 4054 6573 748d b869
181
+ 6e67 208d 8620 7374 6167 2f69 6e67 208d
182
+ 3d20 6575 726f 208d 6520 616e 6420 8d28
183
+ 6f74 688d 2f65 7220 8d3c 2063 6861 7261
184
+ 8d3e 6374 6572 738d 29
185
+ EOF
186
+
187
+ pdu = create_pdu(raw_data)
188
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
189
+ assert_equal 0, pdu.data_coding
190
+
191
+ expected = "Test|ing ˆ stag/ing ~ euro € and {oth\\er [ chara]cters}"
192
+ assert_equal expected, pdu.short_message
193
+ end
194
+
195
+ def test_should_convert_ucs_2_into_utf_8_where_data_coding_indicates_its_presence
196
+ raw_data = <<-EOF
197
+ 0000 003d 0000 0005 0000 0000 0000 0002
198
+ 0001 0134 3437 3830 3330 3239 3833 3700
199
+ 0101 3434 3738 3033 3032 3938 3337 0000
200
+ 0000 0000 0000 0800 0E00 db00 f100 ef00
201
+ e700 f800 6401 13
202
+ EOF
203
+
204
+ pdu = create_pdu(raw_data)
205
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
206
+ assert_equal 8, pdu.data_coding
207
+
208
+ expected = "\303\233\303\261\303\257\303\247\303\270d\304\223" # Ûñïçødē
209
+ assert_equal expected, pdu.short_message
210
+ end
211
+
212
+ def test_should_decode_pound_sign_from_hp_roman_8_to_utf_8_when_data_coding_set_to_1
213
+ raw_data = <<-EOF
214
+ 0000 0096 0000 0005 0000 0000 0000 1b10
215
+ 0005 004d 6f6e 6579 416c 6572 7400 0101
216
+ 3434 3737 3738 3030 3036 3133 0000 0000
217
+ 0000 0000 0100 5fbb 506f 756e 6473 bb20
218
+ EOF
219
+
220
+ pdu = create_pdu(raw_data)
221
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
222
+ assert_equal "£Pounds£ ", pdu.short_message
223
+ end
224
+
225
+ protected
226
+ def create_pdu(raw_data)
227
+ hex_data = [raw_data.chomp.gsub(" ","").gsub(/\n/,"")].pack("H*")
228
+ Smpp::Pdu::Base.create(hex_data)
229
+ end
230
+
231
+ end