Commit 4e9e94faee69ead57813d60be3a039d5e7cafd87

Authored by Adhidarma Hadiwinoto
1 parent 42d1be1a8d
Exists in master

update balance setelah terima uang xltunai

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