empp 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 lijianjun
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
File without changes
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = empp
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to empp
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 lijianjun. See LICENSE.txt for
18
+ further details.
19
+
data/lib/empp.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'empp/empp'
2
+
@@ -0,0 +1,28 @@
1
+ module Empp
2
+ module Constants
3
+ # defined by documents
4
+ EMPPCONNECT = 0x00000001
5
+ EMPP_CONNECT_RESP = 0x80000001
6
+
7
+ EMPP_ACTIVE_TEST = 0x00000008
8
+ EMPP_ACTIVE_TEST_RESP = 0x80000008
9
+
10
+ EMPP_SUBMIT = 0x00000004
11
+ EMPP_SUBMIT_RESP = 0x80000004
12
+
13
+ EMPP_DELIVER = 0x00000005
14
+ EMPP_DELIVER_RESP = 0x80000005
15
+
16
+
17
+ EMPP_CONNECT_OK = 0 # connect OK
18
+
19
+ # defined by programme
20
+ EMPP_CONNECT_ERROR = -1 # broken connect
21
+
22
+ EMPP_SUBMIT_STATUS_SUCCESS = 0
23
+
24
+ EMPP_DELIVER_SUCCESS = -2
25
+ EMPP_DELIVER_FAIL = -3
26
+ end
27
+
28
+ end
@@ -0,0 +1,11 @@
1
+ module Empp
2
+
3
+ class DeliveryState
4
+ attr_accessor :msg_id, :state, :submit_time, :done_time, :dest_terminal_id, :sequence_id
5
+
6
+ def to_s
7
+ "msg_id=#{@msg_id}, state=#{@state}, submit_time=#{@submit_time}, done_time=#{@done_time}, dest_terminal_id=#{@dest_terminal_id}, sequence_id=#{@sequence_id}"
8
+ end
9
+ end
10
+
11
+ end
data/lib/empp/empp.rb ADDED
@@ -0,0 +1,375 @@
1
+ require 'empp/empp_connection'
2
+ require 'empp/constants'
3
+ require 'empp/msg_active_test'
4
+ require 'empp/empp_logger'
5
+ require 'empp/msg_submit'
6
+ require 'empp/utils/hashtable'
7
+ require 'empp/utils/utils'
8
+ require 'empp/empp_parser'
9
+ require 'empp/msg_delivery_resp'
10
+ require 'empp/empp_msg_listener'
11
+ require 'empp/empp_result_listener'
12
+
13
+ require 'thread'
14
+ require 'singleton'
15
+
16
+ module Empp
17
+
18
+ class Empp
19
+
20
+ include Singleton
21
+
22
+ @@configuration = {
23
+ :host => '',
24
+ :port => -1,
25
+ :account_id => '',
26
+ :service_id => '',
27
+ :password => '',
28
+ :logger => nil
29
+ }
30
+
31
+ # message state callback list, when state returns
32
+ # sequence_id => listener
33
+ @@result_listeners = Utils::Hashtable.new
34
+ @@msg_listeners = []
35
+
36
+ def self.config(configuration = {})
37
+ @@configuration.merge! configuration
38
+
39
+ # config logger: debug by default debug:0 info:1 warn:2 error:3 fatal:4
40
+ EmppLogger.config(@@configuration)
41
+ EmppParser::logger = EmppLogger.instance
42
+
43
+ self.instance
44
+ end
45
+
46
+
47
+ def self.send_msg(terminal_ids, msg_content, result_listener = nil)
48
+ self.instance.submit_msg(terminal_ids, msg_content, result_listener)
49
+ end
50
+
51
+ def self.register_msg_listener(msg_listener)
52
+
53
+ if msg_listener && (msg_listener.kind_of?EmppMsgListener)
54
+ @@msg_listeners << msg_listener
55
+ end
56
+
57
+ end
58
+
59
+ def alive?
60
+ @alive
61
+ end
62
+
63
+ private
64
+ def initialize
65
+
66
+ @alive = false
67
+ # it's updated every active response returns and set sequence_id to this value
68
+ @active_test_flag = -1
69
+
70
+ @active_keeper = nil
71
+ @receiver = nil
72
+ @sender = nil
73
+
74
+ @sending_queue = Queue.new
75
+ @sended_list = Utils::Hashtable.new
76
+ @listener = nil
77
+
78
+ @logger = @@configuration[:logger] || EmppLogger.instance
79
+
80
+ # connect to server
81
+ connect(@@configuration[:host], @@configuration[:port], @@configuration[:account_id], @@configuration[:password], @@configuration[:service_id])
82
+
83
+ # automatic reconnect if fails
84
+ @alive_supervisor = Thread.new { start_supervisor }
85
+
86
+ end
87
+
88
+ def connect(host, port, account_id, password, service_id, listener = nil)
89
+ @logger.debug("Enter EmppApi::connect")
90
+
91
+ @host = host
92
+ @port = port
93
+ @account_id = account_id
94
+ @service_id = service_id
95
+ @password = password
96
+
97
+ @empp_connection = EmppConnection.new(host, port, account_id, password, service_id)
98
+ @alive = @empp_connection.connect
99
+
100
+ if @alive
101
+ start_work
102
+ end
103
+
104
+ @logger.debug("Leave EmppApi::connect")
105
+
106
+ @alive
107
+ end
108
+
109
+ public
110
+ def submit_msg(terminal_ids, message, result_listener = nil)
111
+ @logger.debug("Enter EmppApi::submitMsg")
112
+
113
+ if !terminal_ids
114
+ @logger.debug("Leave EmppApi::submitMsg with nil terminal_ids")
115
+ return
116
+ end
117
+
118
+ message ||= ''
119
+
120
+ if terminal_ids.kind_of?String
121
+ terminals = [ terminal_ids ]
122
+ elsif terminal_ids.kind_of?Array
123
+ terminals = terminal_ids
124
+ else
125
+ @logger.warn("EmppApi::submitMsg: Unsupported param type for terminal_ids:#{terminal_ids}")
126
+ return
127
+ end
128
+
129
+ terminals.each do |terminal_id|
130
+ next if terminal_id.length < 11 || terminal_id.length > 14
131
+ next if terminal_id !~ /^((86)|(\+86))?\d+$/
132
+
133
+ msgsubmit = MsgSubmit.new(terminal_id, message, @account_id, @service_id)
134
+
135
+ @sending_queue.push(msgsubmit)
136
+
137
+ # add result listeners
138
+ if result_listener && (result_listener.kind_of?EmppResultListener)
139
+
140
+ msgsubmit.sequence_ids.each do |sequence_id|
141
+ @@result_listeners.put(sequence_id, result_listener)
142
+ end
143
+
144
+ end
145
+
146
+ @logger.info("EmppApi::submitMsg Sending queue size=#{@sending_queue.size}")
147
+ end
148
+
149
+ @logger.debug("Leave EmppApi::submitMsg")
150
+ end
151
+
152
+ private
153
+ def disconnect
154
+ if @active_keeper
155
+ @active_keeper.exit
156
+ end
157
+
158
+ if @receiver
159
+ @receiver.exit
160
+ end
161
+
162
+ if @sender
163
+ @sender.exit
164
+ end
165
+
166
+ @active_keeper = nil
167
+ @receiver = nil
168
+ @sender = nil
169
+ @empp_connection = nil
170
+ end
171
+
172
+ def reconnect
173
+ connect(@host, @port, @account_id, @password, @service_id, @listener)
174
+ end
175
+
176
+ private
177
+
178
+ def start_work
179
+ @active_keeper = Thread.new { start_keeper }
180
+ @receiver = Thread.new { start_receiver }
181
+ @sender = Thread.new { start_sender }
182
+
183
+ end
184
+
185
+ def start_keeper
186
+ @logger.debug("Enter EmppApi::start_keeper")
187
+
188
+ interval = 30 # 3 minutes
189
+ retry_count = 5
190
+
191
+ while @alive && @empp_connection.alive?
192
+
193
+ @logger.info("EmppApi::start_keeper: Active test...")
194
+ old_active_test_flag = @active_test_flag
195
+ activeTest = MsgActiveTest.new
196
+
197
+ @empp_connection.send(activeTest)
198
+
199
+ # waiting for confirmation from ESMP
200
+ sleep interval
201
+
202
+ if old_active_test_flag == @active_test_flag
203
+ retry_count -= 1
204
+ interval = 3 # change interval to little value
205
+
206
+ @logger.warn("EmppApi::start_keeper : No response from ESMP, will retry #{retry_count}")
207
+ if retry_count == 0
208
+ @alive = false # connection is broken
209
+
210
+ # broke the connections, stop the threads
211
+ disconnect
212
+
213
+ @logger.fatal("EmppApi::start_keeper : Empp connection is broken.")
214
+ end
215
+
216
+ else
217
+ retry_count = 5
218
+ interval = 30
219
+ end
220
+
221
+ end # while
222
+
223
+ @logger.debug("Leave EmppApi::start_keeper")
224
+ end
225
+
226
+ def start_receiver
227
+ @logger.debug("Enter EmppApi::start_receiver")
228
+
229
+ while @alive && @empp_connection.alive?
230
+ empp_object = @empp_connection.receive
231
+ @logger.info("EmppApi::start_receiver: receive object=#{empp_object}")
232
+ if empp_object
233
+ processEmppObject(empp_object)
234
+ end
235
+ end
236
+
237
+ @logger.debug("Leave EmppApi::start_receiver")
238
+ end
239
+
240
+ ####################################################
241
+ ## supervise the connection, if it's broken, this ##
242
+ ## will reconnect automatically ##
243
+ ####################################################
244
+ def start_supervisor
245
+ @logger.debug("Enter EmppApi::start_supervisor")
246
+
247
+ interval = 60
248
+
249
+ while true
250
+
251
+ sleep interval
252
+
253
+ if !@alive || !@empp_connection.alive?
254
+ @logger.debug("EmppApi::start_supervisor, connection is broken, begin toreconnect")
255
+ disconnect
256
+ reconnect
257
+ end
258
+
259
+ end
260
+
261
+ @logger.debug("Leave EmppApi::start_supervisor")
262
+ end
263
+
264
+ def processEmppObject(empp_object)
265
+ @logger.debug("Enter EmppApi::processEmppObject")
266
+
267
+ case empp_object.command_id
268
+ when Constants::EMPP_ACTIVE_TEST_RESP
269
+ @active_test_flag = empp_object.sequence_id
270
+ @logger.info("EmppApi::processEmppObject: Active test response is OK.")
271
+
272
+ when Constants::EMPP_SUBMIT_RESP
273
+ sequence_id = empp_object.sequence_id
274
+ terminal_id = @sended_list.delete(sequence_id)
275
+ status = empp_object.status
276
+
277
+ if status == 0
278
+ @logger.debug("EmppApi::processEmppObject: message for #{terminal_id} is correct")
279
+ else
280
+ @logger.warn("EmppApi::processEmppObject: message for #{terminal_id} is invalid, status =#{status}")
281
+ end
282
+ # if @listener
283
+ # @listener.onResponse(Constants::EMPP_SUBMIT_RESP, status, terminal_id)
284
+ # end
285
+
286
+ when Constants::EMPP_DELIVER
287
+ @logger.info("EmppApi::processEmppObject: get delivery object=#{empp_object}")
288
+ terminal_id = empp_object.src_terminal_id
289
+ msg_content = empp_object.msg_content
290
+ registered_delivery = empp_object.registered_delivery
291
+ msg_id = empp_object.msg_id
292
+
293
+ if registered_delivery == 0 # message delivery
294
+
295
+ if empp_object.msg_format == 15
296
+ msg_content = Utils::Utils.convert_gbk_to_utf8(msg_content)
297
+ elsif empp_object.msg_format == 8
298
+ msg_content = Utils::Utils.convert_ucs2_to_utf8(msg_content)
299
+ end
300
+
301
+ respond_to_msg_listeners(terminal_id, msg_content)
302
+
303
+ else # it's a state devilery
304
+
305
+ deliveryState = EmppParser.parseDeliveryState(msg_content)
306
+ @logger.info("EmppApi::processEmppObject: get delivery state=#{deliveryState}")
307
+
308
+ if deliveryState.state.start_with?'DELIV'
309
+
310
+ respond_to_result_listeners(deliveryState.sequence_id, terminal_id, true)
311
+
312
+ else # fail to delivery
313
+
314
+ respond_to_result_listeners(deliveryState.sequence_id, terminal_id, false)
315
+
316
+ end
317
+
318
+ end # end registered_delivery
319
+
320
+ # send response for the delivery
321
+ msg_delivery_resp = MsgDeliveryResp.new
322
+ msg_delivery_resp.msg_id = msg_id
323
+ @empp_connection.send(msg_delivery_resp)
324
+
325
+ end # end case
326
+
327
+
328
+
329
+ @logger.debug("Leave EmppApi::processEmppObject")
330
+ end
331
+
332
+ def start_sender
333
+ @logger.debug("Enter EmppApi::start_sender")
334
+
335
+ while @alive && @empp_connection.alive?
336
+ @logger.debug("EmppApi::before pop")
337
+
338
+ msgObj = @sending_queue.pop
339
+ @logger.debug("EmppApi::after pop, pop obj=#{msgObj}")
340
+ @empp_connection.send(msgObj)
341
+
342
+ @sended_list.put(msgObj.sequence_id, msgObj.terminal_id)
343
+
344
+ sleep 3
345
+ end
346
+
347
+ @logger.debug("Leave EmppApi::start_sender")
348
+ end
349
+
350
+ ####################################################
351
+ ## respond to message listeners ##
352
+ ####################################################
353
+ def respond_to_msg_listeners(terminal_id, msg_content)
354
+
355
+ @@msg_listeners.each do | listener |
356
+ listener.on_message(terminal_id, msg_content)
357
+ end
358
+
359
+ end
360
+
361
+ ########################################################
362
+ # respond to result listeners ##
363
+ #########################################################
364
+ def respond_to_result_listeners(sequence_id, terminal_id, status)
365
+
366
+ result_listener = @@result_listeners.delete(sequence_id)
367
+ if result_listener
368
+ result_listener.on_result(terminal_id, status)
369
+ end
370
+
371
+ end
372
+
373
+ end
374
+
375
+ end