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