Commit dcb9ed61af00d79393e472bdf7357b7387295915

Authored by Adhidarma Hadiwinoto
1 parent 4e9e94faee
Exists in master

perkenalkan: NEED_CHECK_BALANCE

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