Commit b2c88f911e6eebe6268886c48a57e32460c4f2b6

Authored by Adhidarma Hadiwinoto
1 parent dcb9ed61af
Exists in master

hanya eksekusi enablePull jika pre state tidak aktif

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 import logging 3 import logging
4 from logging.handlers import TimedRotatingFileHandler 4 from logging.handlers import TimedRotatingFileHandler
5 import ConfigParser 5 import ConfigParser
6 import json 6 import json
7 from os import getpid 7 from os import getpid
8 import os 8 import os
9 import re 9 import re
10 import signal 10 import signal
11 import sys 11 import sys
12 12
13 config = ConfigParser.RawConfigParser() 13 config = ConfigParser.RawConfigParser()
14 config.read('config.ini') 14 config.read('config.ini')
15 15
16 PORT = config.get('globals','PORT') 16 PORT = config.get('globals','PORT')
17 BAUDRATE = config.getint('globals', 'BAUDRATE') 17 BAUDRATE = config.getint('globals', 'BAUDRATE')
18 PIN = None # SIM card PIN (if any) 18 PIN = None # SIM card PIN (if any)
19 PIN_TRX = config.get('globals', 'PIN_TRX') 19 PIN_TRX = config.get('globals', 'PIN_TRX')
20 20
21 BASE_CHIPINFO = config.get('globals', 'BASE_CHIPINFO') 21 BASE_CHIPINFO = config.get('globals', 'BASE_CHIPINFO')
22 CHIPINFO = BASE_CHIPINFO 22 CHIPINFO = BASE_CHIPINFO
23 23
24 AAA_HOST = config.get('globals', 'AAA_HOST') 24 AAA_HOST = config.get('globals', 'AAA_HOST')
25 CITY = config.get('globals', 'CITY') 25 CITY = config.get('globals', 'CITY')
26 PRODUCTS = config.get('globals', 'PRODUCTS') 26 PRODUCTS = config.get('globals', 'PRODUCTS')
27 27
28 REDIS_HOST = config.get('globals', 'REDIS_HOST') 28 REDIS_HOST = config.get('globals', 'REDIS_HOST')
29 REDIS_PORT = config.getint('globals', 'REDIS_PORT') 29 REDIS_PORT = config.getint('globals', 'REDIS_PORT')
30 REDIS_TTL = config.getint('globals', 'REDIS_TTL') 30 REDIS_TTL = config.getint('globals', 'REDIS_TTL')
31 REDIS_DISABLE_PULL_TTL = config.getint('globals', 'REDIS_DISABLE_PULL_TTL') 31 REDIS_DISABLE_PULL_TTL = config.getint('globals', 'REDIS_DISABLE_PULL_TTL')
32 32
33 PULL_INTERVAL = config.getint('globals', 'PULL_INTERVAL') 33 PULL_INTERVAL = config.getint('globals', 'PULL_INTERVAL')
34 SLEEP_AFTER_TOPUP = config.getint('globals', 'SLEEP_AFTER_TOPUP') 34 SLEEP_AFTER_TOPUP = config.getint('globals', 'SLEEP_AFTER_TOPUP')
35 SLEEP_BETWEEN_BALANCE_N_TOPUP = config.getint('globals', 'SLEEP_BETWEEN_BALANCE_N_TOPUP') 35 SLEEP_BETWEEN_BALANCE_N_TOPUP = config.getint('globals', 'SLEEP_BETWEEN_BALANCE_N_TOPUP')
36 TOPUP_USSD_TIMEOUT = config.getint('globals', 'TOPUP_USSD_TIMEOUT') 36 TOPUP_USSD_TIMEOUT = config.getint('globals', 'TOPUP_USSD_TIMEOUT')
37 SLEEP_AFTER_USSD_ERROR = 180 37 SLEEP_AFTER_USSD_ERROR = 180
38 38
39 NEED_CHECK_BALANCE = False 39 NEED_CHECK_BALANCE = False
40 40
41 MIN_SIGNAL_STRENGTH = 0 41 MIN_SIGNAL_STRENGTH = 0
42 try: 42 try:
43 MIN_SIGNAL_STRENGTH = config.getint('globals', 'MIN_SIGNAL_STRENGTH') 43 MIN_SIGNAL_STRENGTH = config.getint('globals', 'MIN_SIGNAL_STRENGTH')
44 except: 44 except:
45 pass 45 pass
46 if not MIN_SIGNAL_STRENGTH: 46 if not MIN_SIGNAL_STRENGTH:
47 MIN_SIGNAL_STRENGTH = 13 47 MIN_SIGNAL_STRENGTH = 13
48 48
49 MIN_BALANCE = config.getint('globals', 'MIN_BALANCE') 49 MIN_BALANCE = config.getint('globals', 'MIN_BALANCE')
50 50
51 PULL_COUNT = 0 51 PULL_COUNT = 0
52 MSISDN = '' 52 MSISDN = ''
53 BALANCE = 0 53 BALANCE = 0
54 54
55 DISABLE_SEM=0 55 DISABLE_SEM=0
56 DISABLE_SEM_ON_TRX=60 56 DISABLE_SEM_ON_TRX=60
57 57
58 TERMINATING=False 58 TERMINATING=False
59 59
60 LAST_REQUEST_ID = None 60 LAST_REQUEST_ID = None
61 LAST_SN = None 61 LAST_SN = None
62 LAST_PRODUCT = '' 62 LAST_PRODUCT = ''
63 63
64 PULSA = 0 64 PULSA = 0
65 MASA_AKTIF = "" 65 MASA_AKTIF = ""
66 66
67 logger = None 67 logger = None
68 68
69 from gsmmodem.modem import GsmModem 69 from gsmmodem.modem import GsmModem
70 from gsmmodem.exceptions import TimeoutException 70 from gsmmodem.exceptions import TimeoutException
71 71
72 from time import sleep 72 from time import sleep
73 from time import strftime 73 from time import strftime
74 74
75 import redis 75 import redis
76 import requests 76 import requests
77 77
78 import sate24 78 import sate24
79 import xltunai 79 import xltunai
80 80
81 redis_client = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=0) 81 redis_client = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=0)
82 82
83 def signalHandler(signum, frame): 83 def signalHandler(signum, frame):
84 global TERMINATING 84 global TERMINATING
85 85
86 if signum == signal.SIGINT or signum == signal.SIGTERM: 86 if signum == signal.SIGINT or signum == signal.SIGTERM:
87 logger.info('Signal ({0}) received, waiting for next loop to terminate. Terminating...'.format(signum)) 87 logger.info('Signal ({0}) received, waiting for next loop to terminate. Terminating...'.format(signum))
88 TERMINATING = True 88 TERMINATING = True
89 89
90 def createDenyProductFile(product): 90 def createDenyProductFile(product):
91 f = open('{0}.deny'.format(product), 'w') 91 f = open('{0}.deny'.format(product), 'w')
92 f.write(product) 92 f.write(product)
93 f.close() 93 f.close()
94 94
95 def handleSms(sms): 95 def handleSms(sms):
96 global CHIPINFO 96 global CHIPINFO
97 global DISABLE_SEM 97 global DISABLE_SEM
98 global PRODUCTS 98 global PRODUCTS
99 global LAST_PRODUCT 99 global LAST_PRODUCT
100 global LAST_REQUEST_ID 100 global LAST_REQUEST_ID
101 global LAST_SN 101 global LAST_SN
102 global NEED_CHECK_BALANCE 102 global NEED_CHECK_BALANCE
103 103
104 try: 104 try:
105 logger.info(u'Incoming SMS from: {0}; Time: {1}; Message: {2}'.format(sms.number, sms.time, sms.text)) 105 logger.info(u'Incoming SMS from: {0}; Time: {1}; Message: {2}'.format(sms.number, sms.time, sms.text))
106 except: 106 except:
107 logger.info(u'Incoming SMS from: {0}; Time: {1}; Message: BINARY'.format(sms.number, sms.time)) 107 logger.info(u'Incoming SMS from: {0}; Time: {1}; Message: BINARY'.format(sms.number, sms.time))
108 108
109 try: 109 try:
110 epic_key = 'epic.msgin.gw:' + BASE_CHIPINFO 110 epic_key = 'epic.msgin.gw:' + BASE_CHIPINFO
111 redis_client.publish(epic_key + '.message', u'{0}: {1} ({2})'.format(sms.number, sms.text, CHIPINFO)) 111 redis_client.publish(epic_key + '.message', u'{0}: {1} ({2})'.format(sms.number, sms.text, CHIPINFO))
112 except: 112 except:
113 logger.warning('Fail to publish epic message to redis') 113 logger.warning('Fail to publish epic message to redis')
114 114
115 if not xltunai.isValidSender(sms.number): 115 if not xltunai.isValidSender(sms.number):
116 logger.info('Ignoring incoming SMS from invalid sender') 116 logger.info('Ignoring incoming SMS from invalid sender')
117 return 117 return
118 118
119 if sms.text.find('Terimakasih, transaksi CASH IN ke akun') >= 0: 119 if sms.text.find('Terimakasih, transaksi CASH IN ke akun') >= 0:
120 logger.info('handleSms: CASH IN, aktivasi pull jika non aktif') 120 logger.info('handleSms: CASH IN, aktivasi pull jika non aktif')
121 121
122 LAST_SN = xltunai.getSNFromCashInMessage(sms.text) 122 LAST_SN = xltunai.getSNFromCashInMessage(sms.text)
123 logger.info('Override LAST_SN: {0}'.format(LAST_SN)) 123 logger.info('Override LAST_SN: {0}'.format(LAST_SN))
124 124
125 enablePull() 125 enablePull()
126 return 126 return
127 127
128 if sms.text.find('Maaf, transaksi gagal') >= 0: 128 if sms.text.find('Maaf, transaksi gagal') >= 0:
129 pushTopupStatus(LAST_REQUEST_ID, '40', sms.text) 129 pushTopupStatus(LAST_REQUEST_ID, '40', sms.text)
130 createDenyProductFile('ALL'); 130 createDenyProductFile('ALL');
131 PRODUCTS = sate24.removeProduct(PRODUCTS, LAST_PRODUCT) 131 PRODUCTS = sate24.removeProduct(PRODUCTS, LAST_PRODUCT)
132 return 132 return
133 133
134 if sms.text.find('PIN yang Anda masukkan salah. Silahkan ulangi kembali') >= 0: 134 if sms.text.find('PIN yang Anda masukkan salah. Silahkan ulangi kembali') >= 0:
135 pushTopupStatus(LAST_REQUEST_ID, '91', sms.text) 135 pushTopupStatus(LAST_REQUEST_ID, '91', sms.text)
136 return 136 return
137 137
138 if sms.text.find('Maaf, saldo XL-Tunai anda tidak cukup') >= 0: 138 if sms.text.find('Maaf, saldo XL-Tunai anda tidak cukup') >= 0:
139 pushTopupStatus(LAST_REQUEST_ID, '40', sms.text) 139 pushTopupStatus(LAST_REQUEST_ID, '40', sms.text)
140 return 140 return
141 141
142 if sms.text.find('Maaf, layanan ini hanya untuk nomor tujuan prabayar XL') >= 0: 142 if sms.text.find('Maaf, layanan ini hanya untuk nomor tujuan prabayar XL') >= 0:
143 pushTopupStatus(LAST_REQUEST_ID, '14', sms.text) 143 pushTopupStatus(LAST_REQUEST_ID, '14', sms.text)
144 return 144 return
145 145
146 if sms.text.find('Mohon maaf, nomor yang Anda masukkan tidak valid') >= 0: 146 if sms.text.find('Mohon maaf, nomor yang Anda masukkan tidak valid') >= 0:
147 pushTopupStatus(LAST_REQUEST_ID, '14', sms.text) 147 pushTopupStatus(LAST_REQUEST_ID, '14', sms.text)
148 return 148 return
149 149
150 if sms.text.find('Mohon maaf, transaksi Anda melebihi limit nominal bulanan') >= 0: 150 if sms.text.find('Mohon maaf, transaksi Anda melebihi limit nominal bulanan') >= 0:
151 pushTopupStatus(LAST_REQUEST_ID, '40', sms.text) 151 pushTopupStatus(LAST_REQUEST_ID, '40', sms.text)
152 152
153 logger.info('Monthly limit for "{0}" detected, removing from product list'.format(LAST_PRODUCT)) 153 logger.info('Monthly limit for "{0}" detected, removing from product list'.format(LAST_PRODUCT))
154 PRODUCTS = sate24.removeProduct(PRODUCTS, LAST_PRODUCT) 154 PRODUCTS = sate24.removeProduct(PRODUCTS, LAST_PRODUCT)
155 logger.warning('Monthly limit for "{0}" exceeded. New active products: "{1}"'.format(LAST_PRODUCT, PRODUCTS)) 155 logger.warning('Monthly limit for "{0}" exceeded. New active products: "{1}"'.format(LAST_PRODUCT, PRODUCTS))
156 createDenyProductFile(LAST_PRODUCT) 156 createDenyProductFile(LAST_PRODUCT)
157 return 157 return
158 158
159 if sms.text.find('Maaf, transaksi Anda masih dalam proses') >= 0: 159 if sms.text.find('Maaf, transaksi Anda masih dalam proses') >= 0:
160 pushTopupStatus(LAST_REQUEST_ID, '68', sms.text) 160 pushTopupStatus(LAST_REQUEST_ID, '68', sms.text)
161 return 161 return
162 162
163 if sms.text.find('Maaf, saat ini sistem sedang proses maintenance') >= 0: 163 if sms.text.find('Maaf, saat ini sistem sedang proses maintenance') >= 0:
164 pushTopupStatus(LAST_REQUEST_ID, '91', sms.text) 164 pushTopupStatus(LAST_REQUEST_ID, '91', sms.text)
165 return 165 return
166 166
167 if sms.text.find('Anda terima uang XLTunai') >= 0: 167 if sms.text.find('Anda terima uang XLTunai') >= 0:
168 LAST_SN = xltunai.getSNFromReceiveTransferMessage(sms.text) 168 LAST_SN = xltunai.getSNFromReceiveTransferMessage(sms.text)
169 logger.info('Override LAST_SN: {0}'.format(LAST_SN)) 169 logger.info('Override LAST_SN: {0}'.format(LAST_SN))
170 NEED_CHECK_BALANCE = True 170 NEED_CHECK_BALANCE = True
171 return 171 return
172 172
173 if sms.text.find('Kirim uang ke ') == 0: 173 if sms.text.find('Kirim uang ke ') == 0:
174 LAST_SN = xltunai.getSNFromSentTransferMessage(sms.text) 174 LAST_SN = xltunai.getSNFromSentTransferMessage(sms.text)
175 logger.info('Override LAST_SN: {0}'.format(LAST_SN)) 175 logger.info('Override LAST_SN: {0}'.format(LAST_SN))
176 return 176 return
177 177
178 destination = xltunai.getDestinationFromMessage(sms.text) 178 destination = xltunai.getDestinationFromMessage(sms.text)
179 if destination == '': 179 if destination == '':
180 logger.warning('handleSms: gagal parsing nomor tujuan') 180 logger.warning('handleSms: gagal parsing nomor tujuan')
181 return 181 return
182 182
183 nominal = xltunai.getNominalFromMessage(sms.text) 183 nominal = xltunai.getNominalFromMessage(sms.text)
184 if nominal == '': 184 if nominal == '':
185 logger.warning('handleSms: gagal parsing nominal') 185 logger.warning('handleSms: gagal parsing nominal')
186 return 186 return
187 187
188 sn = xltunai.getSNFromMessage(sms.text) 188 sn = xltunai.getSNFromMessage(sms.text)
189 if sn == '': 189 if sn == '':
190 logger.warning('handleSms: gagal parsing SN') 190 logger.warning('handleSms: gagal parsing SN')
191 191
192 192
193 DISABLE_SEM = 0 193 DISABLE_SEM = 0
194 194
195 response_code = xltunai.getResponseCodeByMessage(sms.text) 195 response_code = xltunai.getResponseCodeByMessage(sms.text)
196 196
197 request_id = getRequestIdByNominalDestination(nominal, destination) 197 request_id = getRequestIdByNominalDestination(nominal, destination)
198 if not request_id: 198 if not request_id:
199 logger.info('Unknown request id for nominal:{0} destination:{1}'.format(nominal, destination)) 199 logger.info('Unknown request id for nominal:{0} destination:{1}'.format(nominal, destination))
200 return 200 return
201 201
202 pushTopupStatus(request_id, response_code, sms.text) 202 pushTopupStatus(request_id, response_code, sms.text)
203 try: 203 try:
204 deleteMultipleStoredSms(2) 204 deleteMultipleStoredSms(2)
205 except: 205 except:
206 #logger.warning('Failed on delete SMS') 206 #logger.warning('Failed on delete SMS')
207 pass 207 pass
208 208
209 209
210 def getRequestIdByNominalDestination(nominal, destination): 210 def getRequestIdByNominalDestination(nominal, destination):
211 global CHIPINFO 211 global CHIPINFO
212 212
213 redis_key = sate24.keyByNominalDestination(CHIPINFO, nominal, destination) 213 redis_key = sate24.keyByNominalDestination(CHIPINFO, nominal, destination)
214 #return redis_client.spop(redis_key) 214 #return redis_client.spop(redis_key)
215 return redis_client.rpop(redis_key) 215 return redis_client.rpop(redis_key)
216 216
217 def pushTopupStatus(request_id, response_code, _message, dontparsesn = False): 217 def pushTopupStatus(request_id, response_code, _message, dontparsesn = False):
218 global BALANCE 218 global BALANCE
219 global CHIPINFO 219 global CHIPINFO
220 global LAST_SN 220 global LAST_SN
221 221
222 redis_key = sate24.keyByRequestId(CHIPINFO, request_id) + '.response_code' 222 redis_key = sate24.keyByRequestId(CHIPINFO, request_id) + '.response_code'
223 if response_code == '00': 223 if response_code == '00':
224 redis_client.set(redis_key, response_code) 224 redis_client.set(redis_key, response_code)
225 else: 225 else:
226 redis_response_code = redis_client.get(redis_key) 226 redis_response_code = redis_client.get(redis_key)
227 if redis_response_code == '00': 227 if redis_response_code == '00':
228 logger.info('Ignoring message from success trx ') 228 logger.info('Ignoring message from success trx ')
229 return 229 return
230 230
231 message = "{0} -- Prev balance: {1}".format(_message, BALANCE) 231 message = "{0} -- Prev balance: {1}".format(_message, BALANCE)
232 232
233 timestamp = strftime('%Y%m%d%H%M%S') 233 timestamp = strftime('%Y%m%d%H%M%S')
234 234
235 if response_code == '00' and not dontparsesn: 235 if response_code == '00' and not dontparsesn:
236 sn = xltunai.getSNFromMessage(message) 236 sn = xltunai.getSNFromMessage(message)
237 LAST_SN = sn 237 LAST_SN = sn
238 message = 'SN={0};{1}'.format(sn, message) 238 message = 'SN={0};{1}'.format(sn, message)
239 239
240 push_message = CHIPINFO + '$' + message 240 push_message = CHIPINFO + '$' + message
241 241
242 payload = { 242 payload = {
243 'trans_id': request_id, 243 'trans_id': request_id,
244 'trans_date': timestamp, 244 'trans_date': timestamp,
245 'resp_code': response_code, 245 'resp_code': response_code,
246 'ussd_msg': push_message 246 'ussd_msg': push_message
247 } 247 }
248 248
249 url = AAA_HOST + '/topup' 249 url = AAA_HOST + '/topup'
250 250
251 try: 251 try:
252 logger.info('Sending topup status to AAA') 252 logger.info('Sending topup status to AAA')
253 logger.info(payload) 253 logger.info(payload)
254 r = requests.get(url, params=payload) 254 r = requests.get(url, params=payload)
255 except: 255 except:
256 logger.warning('Error sending topup status to AAA') 256 logger.warning('Error sending topup status to AAA')
257 257
258 try: 258 try:
259 # publish echi topup report ke redis 259 # publish echi topup report ke redis
260 echi_key = 'echi.topup_report.gw:' + BASE_CHIPINFO 260 echi_key = 'echi.topup_report.gw:' + BASE_CHIPINFO
261 261
262 redis_client.publish(echi_key + '.json', json.dumps(payload)) 262 redis_client.publish(echi_key + '.json', json.dumps(payload))
263 263
264 echi_message = timestamp + ' - ' + response_code + ' - ' + message 264 echi_message = timestamp + ' - ' + response_code + ' - ' + message
265 redis_client.publish(echi_key + '.message', echi_message) 265 redis_client.publish(echi_key + '.message', echi_message)
266 except: 266 except:
267 logger.warning('Error publishing topup report to redis') 267 logger.warning('Error publishing topup report to redis')
268 268
269 def getIsDisableRedisKey(): 269 def getIsDisableRedisKey():
270 return CHIPINFO + '.pulldisable' 270 return CHIPINFO + '.pulldisable'
271 271
272 def isPullEnable(): 272 def isPullEnable():
273 redis_key = getIsDisableRedisKey() 273 redis_key = getIsDisableRedisKey()
274 result = 'FALSE' 274 result = 'FALSE'
275 275
276 try: 276 try:
277 result = redis_client.get(redis_key) 277 result = redis_client.get(redis_key)
278 redis_client.expire(redis_key, REDIS_DISABLE_PULL_TTL) 278 redis_client.expire(redis_key, REDIS_DISABLE_PULL_TTL)
279 except: 279 except:
280 return False 280 return False
281 281
282 if not result: 282 if not result:
283 return True 283 return True
284 284
285 return result == 'FALSE' 285 return result == 'FALSE'
286 286
287 def enablePull(): 287 def enablePull():
288 logger.info('Enabling Pull on products {0}'.format(PRODUCTS)) 288 logger.info('Enabling Pull on products {0}'.format(PRODUCTS))
289 redis_key = getIsDisableRedisKey() 289 redis_key = getIsDisableRedisKey()
290 try: 290 try:
291 redis_client.set(redis_key, 'FALSE') 291 redis_client.set(redis_key, 'FALSE')
292 redis_client.expire(redis_key, REDIS_DISABLE_PULL_TTL) 292 redis_client.expire(redis_key, REDIS_DISABLE_PULL_TTL)
293 except: 293 except:
294 return 294 return
295 295
296 def disablePull(): 296 def disablePull():
297 global DISABLE_SEM 297 global DISABLE_SEM
298 global DISABLE_SEM_ON_TRX 298 global DISABLE_SEM_ON_TRX
299 299
300 logger.info('Disabling Pull') 300 logger.info('Disabling Pull')
301 redis_key = getIsDisableRedisKey() 301 redis_key = getIsDisableRedisKey()
302 try: 302 try:
303 redis_client.set(redis_key, 'TRUE') 303 redis_client.set(redis_key, 'TRUE')
304 redis_client.expire(redis_key, REDIS_DISABLE_PULL_TTL) 304 redis_client.expire(redis_key, REDIS_DISABLE_PULL_TTL)
305 except: 305 except:
306 return 306 return
307 307
308 def adviceLastSN(requestId, modem): 308 def adviceLastSN(requestId, modem):
309 global DISABLE_SEM 309 global DISABLE_SEM
310 global LAST_SN 310 global LAST_SN
311 global TOPUP_USSD_TIMEOUT 311 global TOPUP_USSD_TIMEOUT
312 312
313 if not LAST_SN: 313 if not LAST_SN:
314 message = 'Tidak ada trx sebelumnya untuk perbandingan SN. Silahkan bandingkan prev balance dengan trx berikutnya di chip yang sama' 314 message = 'Tidak ada trx sebelumnya untuk perbandingan SN. Silahkan bandingkan prev balance dengan trx berikutnya di chip yang sama'
315 pushTopupStatus(requestId, '68', message) 315 pushTopupStatus(requestId, '68', message)
316 DISABLE_SEM = 0 316 DISABLE_SEM = 0
317 return 317 return
318 318
319 ussd_command = xltunai.getHistoryUSSDCommand() 319 ussd_command = xltunai.getHistoryUSSDCommand()
320 320
321 logger.info(u'Executing advice {0}'.format(ussd_command)) 321 logger.info(u'Executing advice {0}'.format(ussd_command))
322 try: 322 try:
323 response = modem.sendUssd(ussd_command, TOPUP_USSD_TIMEOUT) 323 response = modem.sendUssd(ussd_command, TOPUP_USSD_TIMEOUT)
324 324
325 message = response.message.strip() 325 message = response.message.strip()
326 logger.info(u'USSD response: {0}'.format(message)) 326 logger.info(u'USSD response: {0}'.format(message))
327 327
328 lastSNFromHistory = xltunai.getLastSNFromHistoryMessage(message) 328 lastSNFromHistory = xltunai.getLastSNFromHistoryMessage(message)
329 lastTrxTypeFromHistory = xltunai.getLastTrxTypeFromMessage(message) 329 lastTrxTypeFromHistory = xltunai.getLastTrxTypeFromMessage(message)
330 330
331 if response.sessionActive: 331 if response.sessionActive:
332 response.cancel() 332 response.cancel()
333 333
334 if not lastSNFromHistory: 334 if not lastSNFromHistory:
335 if DISABLE_SEM: 335 if DISABLE_SEM:
336 logger.info('Failed to get last sn from history, retrying in 15 secs') 336 logger.info('Failed to get last sn from history, retrying in 15 secs')
337 sleep(15) 337 sleep(15)
338 adviceLastSN(requestid, modem) 338 adviceLastSN(requestid, modem)
339 339
340 elif lastTrxTypeFromHistory and lastTrxTypeFromHistory.find('RELOAD') < 0: 340 elif lastTrxTypeFromHistory and lastTrxTypeFromHistory.find('RELOAD') < 0:
341 topupMessage = "Topup gagal berdasarkan advice. Trx terakhir adalah P2P Transfer." 341 topupMessage = "Topup gagal berdasarkan advice. Trx terakhir adalah P2P Transfer."
342 pushTopupStatus(requestId, '40', topupMessage) 342 pushTopupStatus(requestId, '40', topupMessage)
343 DISABLE_SEM = 0 343 DISABLE_SEM = 0
344 344
345 elif lastSNFromHistory == LAST_SN: 345 elif lastSNFromHistory == LAST_SN:
346 topupMessage = "Topup gagal berdasarkan advice. {0} = {1}. {2}".format(lastSNFromHistory, LAST_SN, message) 346 topupMessage = "Topup gagal berdasarkan advice. {0} = {1}. {2}".format(lastSNFromHistory, LAST_SN, message)
347 pushTopupStatus(requestId, '40', topupMessage) 347 pushTopupStatus(requestId, '40', topupMessage)
348 DISABLE_SEM = 0 348 DISABLE_SEM = 0
349 349
350 else: 350 else:
351 topupMessage = "SN={0}; Topup berhasil berdasarkan advice. {1}".format(lastSNFromHistory, message) 351 topupMessage = "SN={0}; Topup berhasil berdasarkan advice. {1}".format(lastSNFromHistory, message)
352 LAST_SN = lastSNFromHistory 352 LAST_SN = lastSNFromHistory
353 pushTopupStatus(requestId, '00', topupMessage, True) 353 pushTopupStatus(requestId, '00', topupMessage, True)
354 DISABLE_SEM = 0 354 DISABLE_SEM = 0
355 355
356 except: 356 except:
357 message = "USSD Error: Something wrong when executing USSD advice. Signal strength: {0}".format(modem.signalStrength) 357 message = "USSD Error: Something wrong when executing USSD advice. Signal strength: {0}".format(modem.signalStrength)
358 logger.warning(message) 358 logger.warning(message)
359 pushTopupStatus(requestId, '68', message) 359 pushTopupStatus(requestId, '68', message)
360 360
361 sleep(60) 361 sleep(60)
362 adviceLastSN(requestId, modem) 362 adviceLastSN(requestId, modem)
363 #waitForResultSmsAfterUssdError(modem, task['requestId'], message) 363 #waitForResultSmsAfterUssdError(modem, task['requestId'], message)
364 return 364 return
365 365
366 366
367 367
368 def topupTask(task, modem): 368 def topupTask(task, modem):
369 global LAST_REQUEST_ID 369 global LAST_REQUEST_ID
370 global LAST_PRODUCT 370 global LAST_PRODUCT
371 371
372 if not task: 372 if not task:
373 return 373 return
374 374
375 if task['status'] != 'OK': 375 if task['status'] != 'OK':
376 return 376 return
377 377
378 LAST_REQUEST_ID = task['requestId'] 378 LAST_REQUEST_ID = task['requestId']
379 LAST_PRODUCT = task['product'].upper() 379 LAST_PRODUCT = task['product'].upper()
380 380
381 redis_key = sate24.keyByRequestId(CHIPINFO, task['requestId']) 381 redis_key = sate24.keyByRequestId(CHIPINFO, task['requestId'])
382 redis_client.set(redis_key, task) 382 redis_client.set(redis_key, task)
383 redis_client.expire(redis_key, REDIS_TTL) 383 redis_client.expire(redis_key, REDIS_TTL)
384 384
385 nominal = xltunai.getNominalFromProduct(task['product']) 385 nominal = xltunai.getNominalFromProduct(task['product'])
386 intl_destination = xltunai.toInternationalNumber(task['destination']) 386 intl_destination = xltunai.toInternationalNumber(task['destination'])
387 387
388 redis_key = sate24.keyByNominalDestination(CHIPINFO, nominal, intl_destination) 388 redis_key = sate24.keyByNominalDestination(CHIPINFO, nominal, intl_destination)
389 #redis_client.sadd(redis_key, task['requestId']) 389 #redis_client.sadd(redis_key, task['requestId'])
390 try: 390 try:
391 redis_client.rpush(redis_key, task['requestId']) 391 redis_client.rpush(redis_key, task['requestId'])
392 except: 392 except:
393 redis_client.delete(redis_key) 393 redis_client.delete(redis_key)
394 redis_client.rpush(redis_key, task['requestId']) 394 redis_client.rpush(redis_key, task['requestId'])
395 finally: 395 finally:
396 redis_client.expire(redis_key, REDIS_TTL) 396 redis_client.expire(redis_key, REDIS_TTL)
397 397
398 #pushTopupStatus(task['requestId'], '68', 'Siap mengirimkan trx ke operator') 398 #pushTopupStatus(task['requestId'], '68', 'Siap mengirimkan trx ke operator')
399 399
400 message = 'Executing USSD' 400 message = 'Executing USSD'
401 response_code = '68' 401 response_code = '68'
402 402
403 ussd_command = xltunai.getTopupUSSDCommand(task['destination'], task['product'], PIN_TRX) 403 ussd_command = xltunai.getTopupUSSDCommand(task['destination'], task['product'], PIN_TRX)
404 404
405 logger.info(u'Executing {0}'.format(ussd_command)) 405 logger.info(u'Executing {0}'.format(ussd_command))
406 try: 406 try:
407 response = modem.sendUssd(ussd_command, TOPUP_USSD_TIMEOUT) 407 response = modem.sendUssd(ussd_command, TOPUP_USSD_TIMEOUT)
408 408
409 message = response.message.strip() 409 message = response.message.strip()
410 logger.info(u'USSD response: {0}'.format(message)) 410 logger.info(u'USSD response: {0}'.format(message))
411 411
412 response_code = xltunai.getResponseCodeByUSSDResponse(message) 412 response_code = xltunai.getResponseCodeByUSSDResponse(message)
413 413
414 if response.sessionActive: 414 if response.sessionActive:
415 response.cancel() 415 response.cancel()
416 416
417 except TimeoutException: 417 except TimeoutException:
418 message = "USSD Error: Timeout when executing USSD topup. Signal strength: {0}".format(modem.signalStrength) 418 message = "USSD Error: Timeout when executing USSD topup. Signal strength: {0}".format(modem.signalStrength)
419 logger.warning(message) 419 logger.warning(message)
420 pushTopupStatus(task['requestId'], '68', message) 420 pushTopupStatus(task['requestId'], '68', message)
421 #waitForResultSmsAfterUssdError(modem, task['requestId'], message) 421 #waitForResultSmsAfterUssdError(modem, task['requestId'], message)
422 sleep(15) 422 sleep(15)
423 adviceLastSN(task['requestId'], modem) 423 adviceLastSN(task['requestId'], modem)
424 return 424 return
425 except: 425 except:
426 message = "USSD Error: Something wrong when executing USSD topup. Signal strength: {0}".format(modem.signalStrength) 426 message = "USSD Error: Something wrong when executing USSD topup. Signal strength: {0}".format(modem.signalStrength)
427 logger.warning(message) 427 logger.warning(message)
428 pushTopupStatus(task['requestId'], '68', message) 428 pushTopupStatus(task['requestId'], '68', message)
429 #waitForResultSmsAfterUssdError(modem, task['requestId'], message) 429 #waitForResultSmsAfterUssdError(modem, task['requestId'], message)
430 sleep(15) 430 sleep(15)
431 adviceLastSN(task['requestId'], modem) 431 adviceLastSN(task['requestId'], modem)
432 return 432 return
433 433
434 DISABLE_SEM = DISABLE_SEM_ON_TRX 434 DISABLE_SEM = DISABLE_SEM_ON_TRX
435 pushTopupStatus(task['requestId'], response_code, message) 435 pushTopupStatus(task['requestId'], response_code, message)
436 436
437 def waitForResultSmsAfterUssdError(modem, request_id, last_error_message = ''): 437 def waitForResultSmsAfterUssdError(modem, request_id, last_error_message = ''):
438 logger.info('Sleeping for {0} seconds after an USSD error'.format(SLEEP_AFTER_USSD_ERROR)) 438 logger.info('Sleeping for {0} seconds after an USSD error'.format(SLEEP_AFTER_USSD_ERROR))
439 sleep(SLEEP_AFTER_USSD_ERROR) 439 sleep(SLEEP_AFTER_USSD_ERROR)
440 440
441 redis_key = sate24.keyByRequestId(CHIPINFO, request_id) + '.response_code' 441 redis_key = sate24.keyByRequestId(CHIPINFO, request_id) + '.response_code'
442 response_code = redis_client.get(redis_key) 442 response_code = redis_client.get(redis_key)
443 443
444 if response_code == '68' or response_code == None: 444 if response_code == '68' or response_code == None:
445 445
446 prev_balance = BALANCE 446 prev_balance = BALANCE
447 current_balance = checkBalance(modem, do_not_update = True, return_result = True) 447 current_balance = checkBalance(modem, do_not_update = True, return_result = True)
448 448
449 if current_balance == 0: 449 if current_balance == 0:
450 return 450 return
451 451
452 if current_balance < prev_balance: 452 if current_balance < prev_balance:
453 delta = prev_balance - current_balance 453 delta = prev_balance - current_balance
454 pushTopupStatus( 454 pushTopupStatus(
455 request_id, 455 request_id,
456 '00', 456 '00',
457 'Transaksi dianggap sukses karena saldo berkurang {0}. Last error message: {1}'.format( 457 'Transaksi dianggap sukses karena saldo berkurang {0}. Last error message: {1}'.format(
458 delta, 458 delta,
459 last_error_message 459 last_error_message
460 ) 460 )
461 ) 461 )
462 else: 462 else:
463 pushTopupStatus( 463 pushTopupStatus(
464 request_id, 464 request_id,
465 '40', 465 '40',
466 'Transaksi dianggap gagal karena saldo tidak berkurang. Last error message: {0}'.format(last_error_message) 466 'Transaksi dianggap gagal karena saldo tidak berkurang. Last error message: {0}'.format(last_error_message)
467 ) 467 )
468 468
469 def _saveBalanceToRedis(balance_key, balance_value): 469 def _saveBalanceToRedis(balance_key, balance_value):
470 try: 470 try:
471 redis_client.set(balance_key, balance_value) 471 redis_client.set(balance_key, balance_value)
472 redis_client.expire(balance_key, 3600*24*60) 472 redis_client.expire(balance_key, 3600*24*60)
473 except: 473 except:
474 logger.warning('Failed to save balance to redis') 474 logger.warning('Failed to save balance to redis')
475 475
476 def saveBalanceToRedis(balance): 476 def saveBalanceToRedis(balance):
477 global BASE_CHIPINFO 477 global BASE_CHIPINFO
478 global CHIPINFO 478 global CHIPINFO
479 global MSISDN 479 global MSISDN
480 480
481 try: 481 try:
482 balance = int(balance) 482 balance = int(balance)
483 except ValueError: 483 except ValueError:
484 return 484 return
485 485
486 486
487 data = { 487 data = {
488 'balance.gw:' + BASE_CHIPINFO: balance, 488 'balance.gw:' + BASE_CHIPINFO: balance,
489 'balance.gw:' + CHIPINFO: balance, 489 'balance.gw:' + CHIPINFO: balance,
490 'balance.gw:' + MSISDN: balance 490 'balance.gw:' + MSISDN: balance
491 } 491 }
492 492
493 redis_pipe = redis_client.pipeline() 493 redis_pipe = redis_client.pipeline()
494 494
495 try: 495 try:
496 redis_pipe.mset(data) 496 redis_pipe.mset(data)
497 497
498 for k in data: 498 for k in data:
499 redis_pipe.expire(k, 3600 * 24 * 60) 499 redis_pipe.expire(k, 3600 * 24 * 60)
500 500
501 except: 501 except:
502 logger.warning('Failed to save balance to redis') 502 logger.warning('Failed to save balance to redis')
503 finally: 503 finally:
504 redis_pipe.execute() 504 redis_pipe.execute()
505 505
506 def saveSignalStrengthToRedis(value): 506 def saveSignalStrengthToRedis(value):
507 global BASE_CHIPINFO 507 global BASE_CHIPINFO
508 global CHIPINFO 508 global CHIPINFO
509 global MSISDN 509 global MSISDN
510 510
511 try: 511 try:
512 redis_pipe = redis_client.pipeline() 512 redis_pipe = redis_client.pipeline()
513 redis_client.set('balance.gw:' + BASE_CHIPINFO + '.signal', value) 513 redis_client.set('balance.gw:' + BASE_CHIPINFO + '.signal', value)
514 redis_client.expire('balance.gw:' + BASE_CHIPINFO + '.signal', 15 * 60) 514 redis_client.expire('balance.gw:' + BASE_CHIPINFO + '.signal', 15 * 60)
515 except: 515 except:
516 logger.warning('Failed to save signal strength to redis') 516 logger.warning('Failed to save signal strength to redis')
517 517
518 518
519 def pull(modem): 519 def pull(modem):
520 global PRODUCTS 520 global PRODUCTS
521 global PULL_COUNT 521 global PULL_COUNT
522 global BALANCE 522 global BALANCE
523 global DISABLE_SEM 523 global DISABLE_SEM
524 global MIN_SIGNAL_STRENGTH 524 global MIN_SIGNAL_STRENGTH
525 525
526 if not PRODUCTS: 526 if not PRODUCTS:
527 sleep(60) 527 sleep(60)
528 return 528 return
529 529
530 signalStrength = modem.signalStrength 530 signalStrength = modem.signalStrength
531 if signalStrength < MIN_SIGNAL_STRENGTH: 531 if signalStrength < MIN_SIGNAL_STRENGTH:
532 return 532 return
533 533
534 pull_per_minute = 60 / PULL_INTERVAL 534 pull_per_minute = 60 / PULL_INTERVAL
535 535
536 PULL_COUNT += 1 536 PULL_COUNT += 1
537 if PULL_COUNT % (5 * pull_per_minute) == 0: 537 if PULL_COUNT % (5 * pull_per_minute) == 0:
538 checkBalance(modem) 538 checkBalance(modem)
539 sleep(15) 539 sleep(15)
540 PULL_COUNT = 0 540 PULL_COUNT = 0
541 541
542 if DISABLE_SEM > 0: 542 if DISABLE_SEM > 0:
543 logger.info('SEMAPHORE is still on, delaying pull') 543 logger.info('SEMAPHORE is still on, delaying pull')
544 DISABLE_SEM -= 1 544 DISABLE_SEM -= 1
545 return 545 return
546 546
547 if not isPullEnable(): 547 if not isPullEnable():
548 sleep(60) 548 sleep(60)
549 return 549 return
550 550
551 r = None 551 r = None
552 url = AAA_HOST + '/pull?city=' + CITY + '&nom=' + PRODUCTS 552 url = AAA_HOST + '/pull?city=' + CITY + '&nom=' + PRODUCTS
553 try: 553 try:
554 r = requests.get(url) 554 r = requests.get(url)
555 except: 555 except:
556 logger.warning("Error requesting to AAA") 556 logger.warning("Error requesting to AAA")
557 return 557 return
558 558
559 if not r: 559 if not r:
560 return 560 return
561 561
562 task = sate24.parsePullMessage(r.text) 562 task = sate24.parsePullMessage(r.text)
563 563
564 if task['status'] == 'OK': 564 if task['status'] == 'OK':
565 565
566 logger.info('PULL ' + url + ' => ' + r.text) 566 logger.info('PULL ' + url + ' => ' + r.text)
567 publishAAATaskToRedis(task) 567 publishAAATaskToRedis(task)
568 568
569 if not checkBalance(modem) or BALANCE == 0: 569 if not checkBalance(modem) or BALANCE == 0:
570 pushTopupStatus(task['requestId'], '91', 'Transaksi dibatalkan karena gagal check balance') 570 pushTopupStatus(task['requestId'], '91', 'Transaksi dibatalkan karena gagal check balance')
571 sleep(SLEEP_BETWEEN_BALANCE_N_TOPUP) 571 sleep(SLEEP_BETWEEN_BALANCE_N_TOPUP)
572 return 572 return
573 573
574 sleep(SLEEP_BETWEEN_BALANCE_N_TOPUP) 574 sleep(SLEEP_BETWEEN_BALANCE_N_TOPUP)
575 575
576 topupTask(task, modem) 576 topupTask(task, modem)
577 sleep(SLEEP_AFTER_TOPUP) 577 sleep(SLEEP_AFTER_TOPUP)
578 578
579 def publishAAATaskToRedis(task): 579 def publishAAATaskToRedis(task):
580 try: 580 try:
581 key = 'kimochi.aaa_pull.gw:' + BASE_CHIPINFO 581 key = 'kimochi.aaa_pull.gw:' + BASE_CHIPINFO
582 plain_text = task['timestamp'] + ' - ' + task['member'] + ' isi ' + task['product'] + ' ke ' + task['destination']; 582 plain_text = task['timestamp'] + ' - ' + task['member'] + ' isi ' + task['product'] + ' ke ' + task['destination'];
583 583
584 redis_client.publish(key + '.json', json.dumps(task)) 584 redis_client.publish(key + '.json', json.dumps(task))
585 redis_client.publish(key + '.text', plain_text); 585 redis_client.publish(key + '.text', plain_text);
586 except: 586 except:
587 logger.warning('Error publishing kimochi') 587 logger.warning('Error publishing kimochi')
588 588
589 def publishMessageToRedis(): 589 def publishMessageToRedis():
590 pass 590 pass
591 591
592 def pullLoop(modem): 592 def pullLoop(modem):
593 global TERMINATING 593 global TERMINATING
594 global NEED_CHECK_BALANCE 594 global NEED_CHECK_BALANCE
595 595
596 while True: 596 while True:
597 signalStrength = modem.signalStrength 597 signalStrength = modem.signalStrength
598 saveSignalStrengthToRedis(signalStrength) 598 saveSignalStrengthToRedis(signalStrength)
599 599
600 if NEED_CHECK_BALANCE: 600 if NEED_CHECK_BALANCE:
601 checkBalance(modem) 601 checkBalance(modem)
602 NEED_CHECK_BALANCE = False 602 NEED_CHECK_BALANCE = False
603 603
604 if TERMINATING: 604 if TERMINATING:
605 logger.info('Terminated by request signal') 605 logger.info('Terminated by request signal')
606 sys.exit(0) 606 sys.exit(0)
607 607
608 pull(modem) 608 pull(modem)
609 609
610 sleep(PULL_INTERVAL) 610 sleep(PULL_INTERVAL)
611 611
612 def checkSignal(modem): 612 def checkSignal(modem):
613 logger.info('Signal: {0}'.format(modem.signalStrength)) 613 logger.info('Signal: {0}'.format(modem.signalStrength))
614 try: 614 try:
615 redis_client.set(CHIPINFO + '.signal', modem.signalStrength) 615 redis_client.set(CHIPINFO + '.signal', modem.signalStrength)
616 redis_client.expire(CHIPINFO + '.signal', 3600*24) 616 redis_client.expire(CHIPINFO + '.signal', 3600*24)
617 except: 617 except:
618 logger.warning("Can not save signal strength to redis") 618 logger.warning("Can not save signal strength to redis")
619 619
620 def checkAccount(modem): 620 def checkAccount(modem):
621 try: 621 try:
622 ussd_string = '*123*120*8*3#' 622 ussd_string = '*123*120*8*3#'
623 response = modem.sendUssd(ussd_string, 30) 623 response = modem.sendUssd(ussd_string, 30)
624 logger.info('Account Info: {0}'.format(response.message)) 624 logger.info('Account Info: {0}'.format(response.message))
625 625
626 if response.sessionActive: 626 if response.sessionActive:
627 response.cancel() 627 response.cancel()
628 except: 628 except:
629 logger.warning('Error when requesting account info') 629 logger.warning('Error when requesting account info')
630 return False 630 return False
631 631
632 def checkBalance(modem, do_not_update = False, return_result = False): 632 def checkBalance(modem, do_not_update = False, return_result = False):
633 global BALANCE 633 global BALANCE
634 634
635 _BALANCE = 0 635 _BALANCE = 0
636 636
637 try: 637 try:
638 638
639 ussd_string = '*123*120#' 639 ussd_string = '*123*120#'
640 response = modem.sendUssd(ussd_string, 30) 640 response = modem.sendUssd(ussd_string, 30)
641 _BALANCE = xltunai.getBalanceFromUSSDResponse(response.message) 641 _BALANCE = xltunai.getBalanceFromUSSDResponse(response.message)
642 642
643 if not do_not_update: 643 if not do_not_update:
644 BALANCE = _BALANCE 644 BALANCE = _BALANCE
645 saveBalanceToRedis(BALANCE) 645 saveBalanceToRedis(BALANCE)
646 646
647 logger.info('Balance: {0}'.format(_BALANCE)) 647 logger.info('Balance: {0}'.format(_BALANCE))
648 if response.sessionActive: 648 if response.sessionActive:
649 response.cancel() 649 response.cancel()
650 650
651 if _BALANCE != 0: 651 if _BALANCE != 0:
652 if BALANCE < MIN_BALANCE: 652 if BALANCE < MIN_BALANCE:
653 653
654 logger.info('Disabling pull, balance {0} < {1}'.format(_BALANCE, MIN_BALANCE)) 654 logger.info('Disabling pull, balance {0} < {1}'.format(_BALANCE, MIN_BALANCE))
655 disablePull() 655 disablePull()
656 656
657 else: 657 elif not isPullEnable:
658 658
659 logger.info('Enabling pull, balance {0} > {1}'.format(_BALANCE, MIN_BALANCE)) 659 logger.info('Enabling pull, balance {0} > {1}'.format(_BALANCE, MIN_BALANCE))
660 enablePull() 660 enablePull()
661 661
662 except: 662 except:
663 logger.warning('Error when requesting BALANCE by USSD') 663 logger.warning('Error when requesting BALANCE by USSD')
664 if return_result: 664 if return_result:
665 return 0 665 return 0
666 else: 666 else:
667 return False 667 return False
668 668
669 try: 669 try:
670 redis_client.set(CHIPINFO + '.balance', BALANCE) 670 redis_client.set(CHIPINFO + '.balance', BALANCE)
671 except: 671 except:
672 logger.warning('Failed to save balance to redis') 672 logger.warning('Failed to save balance to redis')
673 673
674 if return_result: 674 if return_result:
675 return _BALANCE 675 return _BALANCE
676 else: 676 else:
677 return True 677 return True
678 678
679 def getPulsaInfo(modem): 679 def getPulsaInfo(modem):
680 global PULSA 680 global PULSA
681 global MASA_AKTIF 681 global MASA_AKTIF
682 682
683 try: 683 try:
684 ussd_string = "*123#" 684 ussd_string = "*123#"
685 response = modem.sendUssd(ussd_string) 685 response = modem.sendUssd(ussd_string)
686 686
687 message = response.message.strip() 687 message = response.message.strip()
688 logger.info('PULSA: {0}'.format(message)) 688 logger.info('PULSA: {0}'.format(message))
689 if response.sessionActive: 689 if response.sessionActive:
690 response.cancel() 690 response.cancel()
691 691
692 PULSA = xltunai.getPulsaFromUssdResponseMessage(message) 692 PULSA = xltunai.getPulsaFromUssdResponseMessage(message)
693 MASA_AKTIF =xltunai.getMasaAktifFromUssdResponseMessage(message) 693 MASA_AKTIF =xltunai.getMasaAktifFromUssdResponseMessage(message)
694 logger.info('PULSA: {0} -- MASA AKTIF: {1}'.format(PULSA, MASA_AKTIF)) 694 logger.info('PULSA: {0} -- MASA AKTIF: {1}'.format(PULSA, MASA_AKTIF))
695 695
696 return message 696 return message
697 697
698 except: 698 except:
699 logger.warning('Error when requesting pulsa info by USSD') 699 logger.warning('Error when requesting pulsa info by USSD')
700 return '' 700 return ''
701 701
702 def getSIMCardInfo(modem): 702 def getSIMCardInfo(modem):
703 try: 703 try:
704 ussd_string = xltunai.getSIMCardInfoUSSDCommand() 704 ussd_string = xltunai.getSIMCardInfoUSSDCommand()
705 response = modem.sendUssd(ussd_string) 705 response = modem.sendUssd(ussd_string)
706 706
707 message = response.message.strip() 707 message = response.message.strip()
708 logger.info('SIM INFO: {0}'.format(message)) 708 logger.info('SIM INFO: {0}'.format(message))
709 if response.sessionActive: 709 if response.sessionActive:
710 response.cancel() 710 response.cancel()
711 711
712 return message 712 return message
713 713
714 except: 714 except:
715 logger.warning('Error when requesting SIM card info by USSD') 715 logger.warning('Error when requesting SIM card info by USSD')
716 return '' 716 return ''
717 717
718 def updateChipInfo(msisdn): 718 def updateChipInfo(msisdn):
719 global BASE_CHIPINFO 719 global BASE_CHIPINFO
720 global CHIPINFO 720 global CHIPINFO
721 global MSISDN 721 global MSISDN
722 722
723 MSISDN = msisdn 723 MSISDN = msisdn
724 if CHIPINFO.find(msisdn) == -1: 724 if CHIPINFO.find(msisdn) == -1:
725 CHIPINFO = BASE_CHIPINFO + '-' + msisdn 725 CHIPINFO = BASE_CHIPINFO + '-' + msisdn
726 726
727 logger.info('CHIPINFO: {0}'.format(CHIPINFO)) 727 logger.info('CHIPINFO: {0}'.format(CHIPINFO))
728 728
729 def removeOverLimitProducts(): 729 def removeOverLimitProducts():
730 global PRODUCTS 730 global PRODUCTS
731 731
732 if os.path.isfile('XL5.deny'): 732 if os.path.isfile('XL5.deny'):
733 logger.warning('XL5.deny found, removing XL5') 733 logger.warning('XL5.deny found, removing XL5')
734 sate24.removeProduct(PRODUCTS, 'XL5') 734 sate24.removeProduct(PRODUCTS, 'XL5')
735 735
736 if os.path.isfile('XL10.deny'): 736 if os.path.isfile('XL10.deny'):
737 logger.warning('XL10.deny found, removing XL10') 737 logger.warning('XL10.deny found, removing XL10')
738 sate24.removeProduct(PRODUCTS, 'XL10') 738 sate24.removeProduct(PRODUCTS, 'XL10')
739 739
740 if os.path.isfile('ALL.deny'): 740 if os.path.isfile('ALL.deny'):
741 logger.warning('ALL.deny found, removing all products') 741 logger.warning('ALL.deny found, removing all products')
742 sate24.removeProduct(PRODUCTS, 'XL5') 742 sate24.removeProduct(PRODUCTS, 'XL5')
743 sate24.removeProduct(PRODUCTS, 'XL10') 743 sate24.removeProduct(PRODUCTS, 'XL10')
744 744
745 745
746 def main(): 746 def main():
747 global logger 747 global logger
748 748
749 log_format = '%(asctime)s %(levelname)s: %(message)s' 749 log_format = '%(asctime)s %(levelname)s: %(message)s'
750 750
751 logging.basicConfig(format=log_format, level=logging.INFO) 751 logging.basicConfig(format=log_format, level=logging.INFO)
752 logger = logging.getLogger(__name__) 752 logger = logging.getLogger(__name__)
753 753
754 logger_formatter = logging.Formatter(log_format) 754 logger_formatter = logging.Formatter(log_format)
755 logger_handler = TimedRotatingFileHandler('logs/log', when='midnight') 755 logger_handler = TimedRotatingFileHandler('logs/log', when='midnight')
756 logger_handler.setFormatter(logger_formatter) 756 logger_handler.setFormatter(logger_formatter)
757 logger.addHandler(logger_handler) 757 logger.addHandler(logger_handler)
758 758
759 requests_logger = logging.getLogger('requests') 759 requests_logger = logging.getLogger('requests')
760 requests_logger.setLevel(logging.WARNING) 760 requests_logger.setLevel(logging.WARNING)
761 761
762 logger.info('Initializing modem...') 762 logger.info('Initializing modem...')
763 763
764 modem = GsmModem(PORT, BAUDRATE, smsReceivedCallbackFunc=handleSms) 764 modem = GsmModem(PORT, BAUDRATE, smsReceivedCallbackFunc=handleSms)
765 modem.smsTextMode = True 765 modem.smsTextMode = True
766 modem.connect(PIN) 766 modem.connect(PIN)
767 767
768 logger.info('Waiting for network coverage...') 768 logger.info('Waiting for network coverage...')
769 modem.waitForNetworkCoverage(10) 769 modem.waitForNetworkCoverage(10)
770 770
771 logger.info('Modem ready') 771 logger.info('Modem ready')
772 772
773 getPulsaInfo(modem) 773 getPulsaInfo(modem)
774 sleep(2) 774 sleep(2)
775 775
776 simcard_info = getSIMCardInfo(modem) 776 simcard_info = getSIMCardInfo(modem)
777 msisdn = xltunai.getMSISDNFromSIMCardInfo(simcard_info) 777 msisdn = xltunai.getMSISDNFromSIMCardInfo(simcard_info)
778 778
779 if not msisdn: 779 if not msisdn:
780 logger.warning('Gagal mendapatkan msisdn, terminating') 780 logger.warning('Gagal mendapatkan msisdn, terminating')
781 sleep(5) 781 sleep(5)
782 sys.exit(2) 782 sys.exit(2)
783 783
784 imsi = modem.imsi 784 imsi = modem.imsi
785 logger.info('MSISDN: {0} -- IMSI: {1}'.format(msisdn, imsi)) 785 logger.info('MSISDN: {0} -- IMSI: {1}'.format(msisdn, imsi))
786 786
787 updateChipInfo(msisdn) 787 updateChipInfo(msisdn)
788 saveSimCardInfo(imsi, msisdn) 788 saveSimCardInfo(imsi, msisdn)
789 789
790 sleep(2) 790 sleep(2)
791 791
792 saveSignalStrengthToRedis(modem.signalStrength) 792 saveSignalStrengthToRedis(modem.signalStrength)
793 793
794 logger.info('Process stored SMS') 794 logger.info('Process stored SMS')
795 try: 795 try:
796 modem.processStoredSms() 796 modem.processStoredSms()
797 except: 797 except:
798 logger.warning('Failed on Process stored SMS') 798 logger.warning('Failed on Process stored SMS')
799 799
800 logger.info('Delete stored SMS') 800 logger.info('Delete stored SMS')
801 try: 801 try:
802 modem.deleteMultipleStoredSms() 802 modem.deleteMultipleStoredSms()
803 except: 803 except:
804 #logger.warning('Failed on delete SMS') 804 #logger.warning('Failed on delete SMS')
805 pass 805 pass
806 806
807 sleep(2) 807 sleep(2)
808 808
809 checkAccount(modem) 809 checkAccount(modem)
810 sleep(5) 810 sleep(5)
811 811
812 removeOverLimitProducts() 812 removeOverLimitProducts()
813 813
814 enablePull() 814 enablePull()
815 815
816 checkBalance(modem) 816 checkBalance(modem)
817 sleep(SLEEP_BETWEEN_BALANCE_N_TOPUP) 817 sleep(SLEEP_BETWEEN_BALANCE_N_TOPUP)
818 818
819 pullLoop(modem) 819 pullLoop(modem)
820 logger.info('Waiting for SMS message...') 820 logger.info('Waiting for SMS message...')
821 try: 821 try:
822 modem.rxThread.join(2**31) # Specify a (huge) timeout so that it essentially blocks indefinitely, but still receives CTRL+C interrupt signal 822 modem.rxThread.join(2**31) # Specify a (huge) timeout so that it essentially blocks indefinitely, but still receives CTRL+C interrupt signal
823 finally: 823 finally:
824 modem.close(); 824 modem.close();
825 825
826 def saveSimCardInfo(imsi, msisdn): 826 def saveSimCardInfo(imsi, msisdn):
827 logger.info('Save sim card info to redis') 827 logger.info('Save sim card info to redis')
828 828
829 data = { 829 data = {
830 'gw': BASE_CHIPINFO, 830 'gw': BASE_CHIPINFO,
831 'imsi': imsi, 831 'imsi': imsi,
832 'msisdn': msisdn, 832 'msisdn': msisdn,
833 'pulsa': PULSA, 833 'pulsa': PULSA,
834 'masa_aktif': MASA_AKTIF 834 'masa_aktif': MASA_AKTIF
835 } 835 }
836 836
837 json_data = json.dumps(data) 837 json_data = json.dumps(data)
838 838
839 with open('simcardinfo.txt', 'w') as f: 839 with open('simcardinfo.txt', 'w') as f:
840 f.write(json_data) 840 f.write(json_data)
841 f.closed 841 f.closed
842 842
843 843
844 map_data = { 844 map_data = {
845 BASE_CHIPINFO + '.simcardinfo': json_data, 845 BASE_CHIPINFO + '.simcardinfo': json_data,
846 'simcardinfo.gw:' + BASE_CHIPINFO: json_data, 846 'simcardinfo.gw:' + BASE_CHIPINFO: json_data,
847 'simcardinfo.imsi:' + imsi: json_data, 847 'simcardinfo.imsi:' + imsi: json_data,
848 'simcardinfo.msisdn:' + msisdn: json_data 848 'simcardinfo.msisdn:' + msisdn: json_data
849 } 849 }
850 850
851 logger.info(map_data) 851 logger.info(map_data)
852 852
853 redis_pipe = redis_client.pipeline() 853 redis_pipe = redis_client.pipeline()
854 854
855 try: 855 try:
856 redis_pipe.mset(map_data) 856 redis_pipe.mset(map_data)
857 857
858 for k in data: 858 for k in data:
859 redis_pipe.expire(k, 3600 * 24 * 60) 859 redis_pipe.expire(k, 3600 * 24 * 60)
860 860
861 except: 861 except:
862 logger.warning('Failed to save simcardinfo to redis') 862 logger.warning('Failed to save simcardinfo to redis')
863 finally: 863 finally:
864 redis_pipe.execute() 864 redis_pipe.execute()
865 865
866 if __name__ == '__main__': 866 if __name__ == '__main__':
867 pidfile = open('pid.txt', 'w') 867 pidfile = open('pid.txt', 'w')
868 pidfile.write(str(getpid())) 868 pidfile.write(str(getpid()))
869 pidfile.close() 869 pidfile.close()
870 870
871 # trap CTRL-C 871 # trap CTRL-C
872 signal.signal(signal.SIGINT, signalHandler) 872 signal.signal(signal.SIGINT, signalHandler)
873 # trap supervisor stop 873 # trap supervisor stop
874 signal.signal(signal.SIGTERM, signalHandler) 874 signal.signal(signal.SIGTERM, signalHandler)
875 875
876 main() 876 main()
877 877