Commit 42d1be1a8d0eda22c17cddc411b443af564cccb9

Authored by Adhidarma Hadiwinoto
1 parent cf4cacd78f
Exists in master

remove overlimit products, verbose

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