def main(): args = parseArgsPy26() if sys.version_info[0] == 2 and sys.version_info[1] < 7 else parseArgs() print ('args:',args) modem = GsmModem(args.port, args.baud) print('Connecting to GSM modem on {0}...'.format(args.port)) try: modem.connect(args.pin, waitingForModemToStartInSeconds=args.wait) except PinRequiredError: sys.stderr.write('Error: SIM card PIN required. Please specify a PIN with the -p argument.\n') sys.exit(1) except IncorrectPinError: sys.stderr.write('Error: Incorrect SIM card PIN entered.\n') sys.exit(1) if args.debug: # Print debug info print('\n== MODEM DEBUG INFORMATION ==\n') print('ATI', modem.write('ATI', parseError=False)) print('AT+CGMI:', modem.write('AT+CGMI', parseError=False)) print('AT+CGMM:', modem.write('AT+CGMM', parseError=False)) print('AT+CGMR:', modem.write('AT+CGMR', parseError=False)) print('AT+CFUN=?:', modem.write('AT+CFUN=?', parseError=False)) print('AT+WIND=?:', modem.write('AT+WIND=?', parseError=False)) print('AT+WIND?:', modem.write('AT+WIND?', parseError=False)) print('AT+CPMS=?:', modem.write('AT+CPMS=?', parseError=False)) print('AT+CNMI=?:', modem.write('AT+CNMI=?', parseError=False)) print('AT+CVHU=?:', modem.write('AT+CVHU=?', parseError=False)) print('AT+CSMP?:', modem.write('AT+CSMP?', parseError=False)) print('AT+GCAP:', modem.write('AT+GCAP', parseError=False)) print('AT+CPIN?', modem.write('AT+CPIN?', parseError=False)) print('AT+CLAC:', modem.write('AT+CLAC', parseError=False)) print() else: # Print basic info print('\n== MODEM INFORMATION ==\n') print('Manufacturer:', modem.manufacturer) print('Model:', modem.model) print('Revision:', modem.revision if modem.revision != None else 'N/A') print('\nIMEI:', modem.imei if modem.imei != None else 'N/A') print('IMSI:', modem.imsi if modem.imsi != None else 'N/A') print('\nNetwork:', modem.networkName) print('Signal strength:', modem.signalStrength) print()
def run(self): logging.info("Modem thread running") global modem rxListenLength = 10 init_count = 0 while self.running and init_count > -1: try: init_count = init_count + 1 modem = GsmModem(PORT, BAUDRATE, incomingCallCallbackFunc=handleIncomingCall) logging.info("Initializing modem, try {0}.".format(init_count)) modem.connect(PIN) init_count = -1 except TimeoutException as e: logging.critical("Failed to initialize the GSM module: {0}", e) modem.close() logging.info('Waiting for incoming calls...') while self.running: try: #waitForNetworkCoverage() self.signalStrength = modem.signalStrength self.networkName = modem.networkName serving_cell = self.CGED_REGEX.match( modem.write("AT+CGED=3")[0]) if serving_cell: mcc = serving_cell.group(1) mnc = serving_cell.group(2) lac = serving_cell.group(3) ci = serving_cell.group(4) self.cellInfo = "{0}/{1}/{2}/{3}".format(mcc, mnc, lac, ci) # Comms are handled elsewhere so we could eventually just sleep, waiting #time.sleep(rxListenLength) modem.rxThread.join(rxListenLength) except (InterruptedException, PinRequiredError, IncorrectPinError, TimeoutException): logging.error("rxThread died: {0}".format(sys.exc_info()[0])) modem.close() logging.info("Modem closed.")
def run(self): logging.info("Modem thread running") global modem rxListenLength = 10 init_count = 0 while self.running and init_count > -1: try: init_count = init_count + 1 modem = GsmModem(PORT, BAUDRATE, incomingCallCallbackFunc=handleIncomingCall) logging.info("Initializing modem, try {0}.".format(init_count)) modem.connect(PIN) init_count = -1 except TimeoutException as e: logging.critical("Failed to initialize the GSM module: {0}", e) modem.close() logging.info('Waiting for incoming calls...') while self.running: try: #waitForNetworkCoverage() self.signalStrength = modem.signalStrength self.networkName = modem.networkName serving_cell=self.CGED_REGEX.match(modem.write("AT+CGED=3")[0]) if serving_cell: mcc=serving_cell.group(1) mnc=serving_cell.group(2) lac=serving_cell.group(3) ci=serving_cell.group(4) self.cellInfo="{0}/{1}/{2}/{3}".format(mcc, mnc, lac, ci) # Comms are handled elsewhere so we could eventually just sleep, waiting #time.sleep(rxListenLength) modem.rxThread.join(rxListenLength) except (InterruptedException, PinRequiredError, IncorrectPinError, TimeoutException): logging.error("rxThread died: {0}".format(sys.exc_info()[0])) modem.close() logging.info("Modem closed.")
def listen(): global gsm jeedom_socket.open() logging.debug("Start listening...") try: logging.debug("Connecting to GSM Modem...") gsm = GsmModem(_device, int(_serial_rate), smsReceivedCallbackFunc=handleSms) if _text_mode == 'yes': logging.debug("Text mode true") gsm.smsTextMode = True else: logging.debug("Text mode false") gsm.smsTextMode = False if _pin != 'None': logging.debug("Enter pin code : " + _pin) gsm.connect(_pin) else: gsm.connect() if _smsc != 'None': logging.debug("Configure smsc : " + _smsc) gsm.write('AT+CSCA="{0}"'.format(_smsc)) logging.debug("Waiting for network...") gsm.waitForNetworkCoverage() logging.debug("Ok") try: jeedom_com.send_change_immediate({ 'number': 'network_name', 'message': str(gsm.networkName) }) except Exception, e: if str(e).find('object has no attribute') <> -1: pass logging.error("Exception: %s" % str(e)) try: gsm.write('AT+CPMS="ME","ME","ME"') gsm.write('AT+CMGD=1,4') except Exception, e: if str(e).find('object has no attribute') <> -1: pass logging.error("Exception: %s" % str(e))
def listen(): global gsm jeedom_socket.open() logging.debug("Start listening...") try: logging.debug("Connecting to GSM Modem...") gsm = GsmModem(_device, int(_serial_rate), smsReceivedCallbackFunc=handleSms) if _text_mode == 'yes' : logging.debug("Text mode true") gsm.smsTextMode = True else : logging.debug("Text mode false") gsm.smsTextMode = False if _pin != 'None': logging.debug("Enter pin code : "+_pin) gsm.connect(_pin) else : gsm.connect() if _smsc != 'None' : logging.debug("Configure smsc : "+_smsc) gsm.write('AT+CSCA="{0}"'.format(_smsc)) logging.debug("Waiting for network...") gsm.waitForNetworkCoverage() logging.debug("Ok") try: jeedom_com.send_change_immediate({'number' : 'network_name', 'message' : str(gsm.networkName) }); except Exception, e: if str(e).find('object has no attribute') <> -1: pass logging.error("Exception: %s" % str(e)) try: gsm.write('AT+CPMS="ME","ME","ME"') gsm.write('AT+CMGD=1,4') except Exception, e: if str(e).find('object has no attribute') <> -1: pass logging.error("Exception: %s" % str(e))
def main(): logging.basicConfig(level=logging.DEBUG) args = parseArgsPy26() if sys.version_info[0] == 2 and sys.version_info[1] < 7 else parseArgs() print ('args:',args) modem = GsmModem(args.port, args.baud) print('Connecting to GSM modem on {0}...'.format(args.port)) try: modem.connect(args.pin, waitingForModemToStartInSeconds=args.wait) except PinRequiredError: sys.stderr.write('Error: SIM card PIN required. Please specify a PIN with the -p argument.\n') sys.exit(1) except IncorrectPinError: sys.stderr.write('Error: Incorrect SIM card PIN entered.\n') sys.exit(1) if args.debug: # Print debug info print('\n== MODEM DEBUG INFORMATION ==\n') print('ATI', modem.write('ATI', parseError=False)) print('AT+CGMI:', modem.write('AT+CGMI', parseError=False)) print('AT+CGMM:', modem.write('AT+CGMM', parseError=False)) print('AT+CGMR:', modem.write('AT+CGMR', parseError=False)) print('AT+CFUN=?:', modem.write('AT+CFUN=?', parseError=False)) print('AT+WIND=?:', modem.write('AT+WIND=?', parseError=False)) print('AT+WIND?:', modem.write('AT+WIND?', parseError=False)) print('AT+CPMS=?:', modem.write('AT+CPMS=?', parseError=False)) print('AT+CNMI=?:', modem.write('AT+CNMI=?', parseError=False)) print('AT+CVHU=?:', modem.write('AT+CVHU=?', parseError=False)) print('AT+CSMP?:', modem.write('AT+CSMP?', parseError=False)) print('AT+GCAP:', modem.write('AT+GCAP', parseError=False)) print('AT+CPIN?', modem.write('AT+CPIN?', parseError=False)) print('AT+CLAC:', modem.write('AT+CLAC', parseError=False)) print() else: # Print basic info print('\n== MODEM INFORMATION ==\n') print('Manufacturer:', modem.manufacturer) print('Model:', modem.model) print('Revision:', modem.revision if modem.revision != None else 'N/A') print('\nIMEI:', modem.imei if modem.imei != None else 'N/A') print('IMSI:', modem.imsi if modem.imsi != None else 'N/A') print('\nNetwork:', modem.networkName) print('Signal strength:', modem.signalStrength) print()
class Transmitter: #Initalize Transmitter object attributes. def __init__(self, port='/dev/ttyUSB2', qmi_path='/dev/cdc-wdm0', baud='115200', **kwargs): #Ensure that we're running as root. if not os.geteuid() == 0: raise Exception("Must run as root!") self.ensure_sim_card_connected_to_network(qmi_path) #self._configure_ser_connection_to_usb(self.usb_path) self._connect_to_modem(port, baud) #Globals for Concatenated Short Messages (PDU) self.message_ref = 0x00 self.CSM_ref = 0x00 #Add pgsmm modem connection def _connect_to_modem(self, port, baud): self.modem = GsmModem(port, baud) print("connecting...") self.modem.connect() check = self.send_AT('AT') print(check) #Configure serial connection settings. def _configure_ser_connection_to_usb(self, usb_port): self.ser = serial.Serial( port=usb_port, baudrate=9600, #Might be able to increase this. pgsmm uses 115200 parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_TWO, bytesize=serial.EIGHTBITS) time.sleep(5) #Ensure that AT command 'AT' returns echoed 'AT' (multiple tries if necessary). for connection_attempt in range(15): check_AT = self.send_AT('AT') #Ensure that AT message is returned. if check_AT: if check_AT.startswith('AT'): return else: time.sleep(5) else: time.sleep(15) print "Function: _configure_ser_connection_to_usb\n Resetting sim hat because we hit the 'AT not responding' error." #We experienced a strange error where the AT (sim card) hat won't echo AT calls. The only way we #know of to fix it is to perform a QMICLI reset of the sim card (hat). self._reset_sim_hat(self.usb_path) #Check that the SIM card via the Qmicli interface is connected to the mobile network. #Default for raspberry pi + waveshare SIM7600 Hat is /dev/cdc-wdm0 #Must run as root def ensure_sim_card_connected_to_network(self, sim_path): #Check if our SIM card is connected to the network or not. sim_mode = self._get_qmicli_mode(sim_path) #If not online, try to turn it on. if sim_mode != "online": #If sim/modem is reset when the serial connection is open, it will clobber /dev/ttyUSB2. #So we close the serial connection while we perform the reset. #if self.ser.isOpen() == True: # self.ser.close() #print "Sim card was off, turning online." self._set_qmicli_mode('online', sim_path) timeout_count = 0 #Verify that it comes online. while (1): time.sleep(10) sim_mode = self._get_qmicli_mode(sim_path) if sim_mode == 'online': #We're online! Escape bonds of while loop and return. print "Successfuly set sim card online." break #Otherwise, let's try to turn it online. else: print "Sim card is being reset to turn it online." time.sleep(10) self._set_qmicli_mode('reset', sim_path) time.sleep(30) #For potential debugging. We expect SIM mode = 'low-power' here after reset. get_response = self._get_qmicli_mode(sim_path) if 'low-power' != get_response: print "Warning, SIM Mode is: " + get_response else: print "We're in low power mode, please wait as we turn SIM online." time.sleep(1) self._set_qmicli_mode('online', sim_path) time.sleep(20) timeout_count += 1 #Time out after a few minutes of trying if timeout_count > 2: raise Exception( "The SIM card could not be set to online mode!") #Turn serial connection back on after resetting sim/modem. #self._configure_ser_connection_to_usb(self.usb_path) return 1 #Looks like we're online! Return true. else: return 1 def _reset_sim_hat(self, sim_path): #set offline self._set_qmicli_mode('offline', sim_path) #then call ensure_sim_connected self.ensure_sim_card_connected_to_network(sim_path) #Check to make sure the sim_path exists, which implies that the modem can accept qmicli commands def _check_sim_path(self, sim_path): #qmicli clobbers path during 'reset' so the while loop ensures no false negatives. timeout_count = 0 while timeout_count < 15: #Ensure that path to SIM card exists. if os.path.exists(sim_path): return 1 else: time.sleep(1) timeout_count += 1 raise Exception("The SIM card path " + sim_path + " does not exist!") #Sets our SIM card to the specified mode (e.g. 'reset', 'online', etc). def _set_qmicli_mode(self, mode, sim_path): self._check_sim_path(sim_path) os.system("qmicli -d " + sim_path + " --dms-set-operating-mode='" + mode + "'") #Returns SIM card mode (e.g. 'offline', 'online', 'low-power', 'reset', etc. def _get_qmicli_mode(self, sim_path): self._check_sim_path(sim_path) get_output = os.popen('qmicli -d ' + sim_path + ' --dms-get-operating-mode') output_read = get_output.read() mode_match = re.search("Mode: '([a-z-]+)'", output_read) if mode_match.group(1) is not None: return mode_match.group(1) else: print "Error: we could not read mode for:\n" + output_read return 0 #Send AT command to modem using pgsmm. def send_AT(self, AT): prune = self.modem.write(AT) print('at: ', AT) print('prune: ', prune) response = re.search(r"[u'(.+)']", prune) print(response.group(0)) return response.group(0) #Send AT command to modem. #def send_AT(self, AT, waiting_for_chr_26 = 0): #Open up our serial connection to the SIM self.ser.isOpen() #First send a simple 'AT' command, and confirm it returns 'OK'. #This will indicate to us that our SIM is working and ready for more AT commands. for filter_AT_response in range(15): #If we're waiting for chr(26) inside a text message - an echo test won't work so break away! if waiting_for_chr_26: break ok_response = '' self.ser.write("AT\r\n") while self.ser.inWaiting() > 0: ok_response += self.ser.read(1) #If our AT is ready, then break away. if ok_response.startswith('AT'): break #If we've hit a weird error, and we're inside a text message, notify and fix it. elif ok_response.endswith('> AT'): print "We hit an unknown error, waiting for chr(26) to end AT text message!" self.ser.write("Sorry there was an error" + chr(26)) while self.ser.inWaiting() > 0: ok_response += self.ser.read(1) print "Hopefully we fixed it, here is the AT response: ~" + ok_response + "~" continue time.sleep(5) if filter_AT_response >= 14: #raise Exception('Could not verify AT functionality by an AT echo') print "Function: send_AT\n Resetting sim hat because we hit the 'AT not responding' error." #We experienced a strange error where the AT (sim card) hat won't echo AT calls. The only way we #know of to fix it is to perform a QMICLI reset of the sim card (hat). self._reset_sim_hat(self.usb_path) self.ser.write(AT + "\r\n") time.sleep(1) ser_response = '' while self.ser.inWaiting() > 0: ser_response += self.ser.read(1) return ser_response #Remove this probably #Check if SIM card configured for SMS text mode. def check_sms_mode(self): sms_mode = self.send_AT('AT+CMGF?') regex_mode_result = re.search("\+CMGF:\s+([01])", sms_mode) if regex_mode_result: #If CMGF = 1, our sim is in text mode if regex_mode_result.group(1) == '1': return "text_mode_on" #If CMGF = 0, our sim is in pdu mode elif regex_mode_result.group(1) == '0': return "text_mode_off" #We ran into this bug once before, hopefully we can narrow it down with this exception: raise Exception( "Error: our CMGF query didn't return 1 or 0, here's what we got back: ~" + sms_mode + "~") #Needed for long text #Set SMS for text mode. sms_mode of 1 = texting (this is what we want), 0 = Programmable data unit PDU. def set_sms_mode(self, sms_mode): sms_mode = str(sms_mode) #convert num to string sms_mode_response = self.send_AT('AT+CMGF=' + sms_mode) print("sms mode response: " + sms_mode_response) ok = re.findall("OK", sms_mode_response) if (not ok): raise Exception("SMS mode ", sms_mode, " was not successfully set\n") #Original function source: https://guiott.com/GSMcontrol/Python_GSM/_modules/gsmmodem/pdu.html #Given a bytearray of octets, pack into septets and return a bytearray of them. def packSeptets(self, octets, padBits=6): result = bytearray() #Make the array iteratable. I think this allows the for loop to work on a bytearray. octets = iter(octets) shift = padBits #zeros need to be shifted in from prevSeptet in order to insert padding bits. prevSeptet = 0x00 for octet in octets: #For septet packing we do a bitwise and with the 7 least sig digits. septet = octet & 0x7f if shift == 7: # prevSeptet has already been fully added to result shift = 0 prevSeptet = septet continue #Bitmagic septet packing. An explaination for septet packing can be found here: # https://www.codeproject.com/Tips/470755/Encoding-Decoding-7-bit-User-Data-for-SMS-PDU-PDU b = ((septet << (7 - shift)) & 0xFF) | (prevSeptet >> shift) prevSeptet = septet shift += 1 result.append(b) if shift != 7: # There is a bit "left over" from prevSeptet result.append(prevSeptet >> shift) return result #Convert a string of characters to GSM7 encoded bytearray. #Original function source: https://guiott.com/GSMcontrol/Python_GSM/_modules/gsmmodem/pdu.html def encode_gsm_octets(self, plaintext): if type(plaintext) != str: plaintext = str(plaintext) result = bytearray() #Make sure chars are in utf-8 format. for c in plaintext.decode('utf-8'): #The index corresponds to the gsm7 number(int/hex/binary) representation. idx = gsm.find(c) if idx != -1: result.append(idx) else: idx = ext.find(c) if idx != -1: result.append(27) result.append(idx) return result #Original function source: https://guiott.com/GSMcontrol/Python_GSM/_modules/gsmmodem/pdu.html #Divides a long text that needs to be broken up and sent via PDU. Some GSM7 chars are 2 bytes long, # so this function makes sure that the converted octet length doesn't exceed 153. def divide_text(self, plainText): result = [] plainStartPtr = 0 plainStopPtr = 0 chunkByteSize = 0 while plainStopPtr < len(plainText): char = plainText[plainStopPtr] idx = gsm.find(char) if idx != -1: chunkByteSize = chunkByteSize + 1 elif char in ext: chunkByteSize = chunkByteSize + 2 else: raise ValueError( 'Cannot encode char "{0}" using GSM-7 encoding'.format( char)) plainStopPtr = plainStopPtr + 1 if chunkByteSize > 153: plainStopPtr = plainStopPtr - 1 if chunkByteSize >= 153: result.append(plainText[plainStartPtr:plainStopPtr]) plainStartPtr = plainStopPtr chunkByteSize = 0 if chunkByteSize > 0: result.append(plainText[plainStartPtr:]) return result #Converts a number string into the reverse nibble, Binary Coded Decimal bytearray needed for Concatenated Short Message. def convert_to_DA(self, number): if len(number) == 10: destination_address = '1' + number elif len(number) == 11: destination_address = number else: raise Exception( "Failed to convert to Destination Address: input has the wrong number of digits!" ) #F indicates the end of the Destination Address. destination_address = destination_address + 'F' result = bytearray() #From 0 to the length of the DA, count i by 2. for i in xrange(0, len(destination_address), 2): #(Take slice from i to (i+2)-1 [i:i+2]) (and reverse it [::-1]) octet = destination_address[i:i + 2][::-1] #Convert the 16 bit octet string into a number. number = int(octet, 16) result.append(number) return result #Send a series of Concatenated Short Messages in PDU mode. The recipient's phone (Terminal Equipment) will re-assemble. #Function composed from SMS/Octet map in a way that is easy to read, walk through. def send_long_text(self, number, message): self.set_sms_mode('0') #Set modem to PDU mode. service_center_address = 0x00 #Value of 00 tells the modem to use the default address. #1 in the least sig bit indicates SMS-SUBMIT. 1 in the 7th least sig bit indicates the presence of the User Data Header. #b 0100 0001 = 0x41 message_type_indicator = 0x41 #self.message_ref #Counts up for each pdu short message we send. DA_len = 0x0B #Indicates the length of the Destination Address. number_plan_ID = 0x91 #Indicates how to interpret the DA destination_address = self.convert_to_DA( number) #Reverse nibble, Binary Coded Decimal, ending with F. protocol_ID = 0x00 #Value of 00 indicates a 'normal SMS' data_coding_scheme = 0x00 #Value of 00 indicates that the payload will be coded in GSM-7. user_data_length = 0x00 #Length of the payload in septets. user_data_header_length = 0x05 #A static 5 octets will be the length of the UDH for our CSM usage. information_element_identifier = 0x00 #Value of 00 indicates that this IE will be a CSM header. IEI_length = 0x03 #The IE will be 3 octets long. #self.CSM_ref #Unique identifier for Concatenated Short Message group. total_CSM_parts = 0x00 #Number of parts of the CSM group. CSM_sequence_number = 0x01 #The current iteration of the part (starting with 1). user_data = bytearray() #GSM-7 encoded payload data. message_list_pdu = [] #divide the long text into segments that won't cause errors (hex length <= 153), keeping the extended alphabet in mind. message_list_pdu = self.divide_text(message) total_CSM_parts = len(message_list_pdu) pdus = [] #Line up the bytes of each part and send it. for SM_part in message_list_pdu: pdu = bytearray() octets = self.encode_gsm_octets(SM_part) #byte array #(One of the) Fill bits calculation: #UDHL+IEI+IEIL+CSM_ref+total_CSM_parts+CSM_sequence_number = 6 octets #number of septets + 7: (49/7 = 7) 6 octets of bits = 48. Need 1 bit to get to 49 which is divisible by 7. user_data_length = len(octets) + 7 print "udl = " + str(user_data_length) user_data = self.packSeptets(octets) #byte array pdu.append(service_center_address) pdu.append(message_type_indicator) pdu.append(self.message_ref) self.message_ref += 1 pdu.append(DA_len) pdu.append(number_plan_ID) #Extend is used to concatenate arrays. pdu.extend(destination_address) pdu.append(protocol_ID) pdu.append(data_coding_scheme) pdu.append(user_data_length) pdu.append(user_data_header_length) pdu.append(information_element_identifier) pdu.append(IEI_length) pdu.append(self.CSM_ref) pdu.append(total_CSM_parts) pdu.append(CSM_sequence_number) CSM_sequence_number += 1 pdu.extend(user_data) #Don't count the service_center_address as it is not part of the PDU protocol layer. pdu_length = str(len(pdu) - 1) print("AT length: " + pdu_length) print("SM part " + str(CSM_sequence_number - 1) + ":") pdu_string = '' #Python likes to remove preceeding zeros from hex numbers. This makes sure the zeros are not removed. for byte in pdu: #If there are fewer than 2 digits, fill with up to 2 zeros. pdu_string += hex(byte)[2:].zfill(2) print(pdu_string) #Send the modem the CMGS command in the format to send a text out, where chr(26) is the required ctrl+Z that denotes EOF response1 = self.send_AT('AT+CMGS=' + pdu_length + '\r\n') response2 = self.send_AT(pdu_string + chr(26), 1) print('response1: ' + response1) print('response2: ' + response2) #After the set of Concatenated Short Messages finishes, increment so the next group gets a different ref number. self.CSM_ref += 1 #Replace with pgsmm version #Sends a text to the specified number, with the specified message. def send_text(self, number, message): print "Send text has been called with number " + number + " and message " + message #We've reached the upper limit of a single SMS; send multi-part instead. if len(message) > 160: self.send_long_text(number, message) #Make sure texting is turned on in the SIM card. current_sms_mode = self.check_sms_mode() if current_sms_mode == "text_mode_off": self.set_sms_mode("1") elif current_sms_mode == "text_mode_error": raise Exception( "SMS mode query error. There may be a problem with modem communication." ) #Send the modem the CMGS command in the format to send a text out, where chr(26) is the required ctrl+Z that denotes EOF response1 = self.send_AT('AT+CMGS="' + number + '"\r\n') response2 = self.send_AT(message + chr(26), 1) def send_text_to_host(self, host_number, tenant_number, message): host_message = "Text sent to ~" + tenant_number + "~ :\n" + message self.send_text(host_number, host_message) #Returns array of SMS objects, returning all texts on SIM card. def get_all_texts(self): sms_array = [] text_list = self.send_AT('AT+CMGL="ALL"') text_array = text_list.split('+CMGL:') for text_array_index, text in enumerate(text_array): text_regex = '^\s*([0-9]+),\"([A-Z\s]+)\",\"\+?1?([0-9]{10})\",\"[^\"]*\",\"([^\"]+)\"\s+(.*)$' re_result = re.search(text_regex, text, re.DOTALL) if re_result: index = re_result.group(1) status = re_result.group(2) phone = re_result.group(3) date = re_result.group(4) message = re_result.group(5) #Remove newlines from all messages and the 'OK' AT command from the last message. if text_array_index == len(text_array) - 1: #'.*' at end removes +Class0 status messages (we hope). message = re.sub('[\r\n]+OK\r\n.*$', '', message) else: message = re.sub('[\r\n]+$', '', message) #Put each SMS in message array. sms_obj = SMS(index, status, phone, date, message) sms_array.append(sms_obj) return sms_array #Deletes text with specified index from SIM card. def delete_text(self, index): if self._does_message_at_index_exist(index): command = 'AT+CMGD=' + index self.send_AT(command) if self._does_message_at_index_exist(index): return "text at index '" + index + "' not deleted" else: return "text at index '" + index + "' deleted" else: return "text at index '" + index + "' not found" #Probes SIM card to see if message at index exists. def _does_message_at_index_exist(self, index): sms_list = self.get_all_texts() for sms in sms_list: if sms.index == index: return 1 return 0 #Saves array of SMS objects to json file. def save_sms_obj_to_json_file(self, text_array, filename): if self._is_sms_array(text_array): #Create dictionary (hashlike structure) data = {} #Create an array data['sms'] = [] for sms in text_array: data['sms'].append({ 'index': sms.index, 'status': sms.status, 'phone': sms.phone, 'date': sms.date, 'message': sms.message }) outfile = open(filename, 'w') json.dump(data, outfile) outfile.close() #Returns array of SMS message objects taken from json file. def json_file_to_sms_array(self, filename): json_file = open(filename, 'r') read_data = json.load(json_file) json_file.close() sms_array = [] for sms_json in read_data['sms']: sms_obj = SMS(sms_json['index'], sms_json['status'], sms_json['phone'], sms_json['date'], sms_json['message']) sms_array.append(sms_obj) return sms_array def append_texts_to_db_file(self, sms_array, sms_database_file): if self._is_sms_array(sms_array): #Write new sms messages to database. #First check if sms database file exists. try: open(sms_database_file) #If doesn't exist create it and write new sms messages to it. except IOError: self.save_sms_obj_to_json_file(sms_array, sms_database_file) #Otherwise, read text from database and append sms_array and save to file. else: db_sms_array = self.json_file_to_sms_array(sms_database_file) full_db_sms_array = db_sms_array + sms_array self.save_sms_obj_to_json_file(full_db_sms_array, sms_database_file) def delete_texts_from_sim_card(self, sms_array): if self._is_sms_array(sms_array): for sms in sms_array: self.delete_text(sms.index) #Do we have an array containing SMS objects def _is_sms_array(self, sms_array): if len(sms_array) > 0: for sms in sms_array: if not isinstance(sms, SMS): raise Exception( "The objects in the inputted array are not SMS objects!" ) #Array has elements, and those elements are SMS objects. return 1
#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import print_function #Don't write a pesky .pyc file. import sys sys.dont_write_bytecode = True #sys.path.append('/path/to/application/app/folder') from gsmmodem.modem import GsmModem #from gsmtermlib.terminal import RawTerm PORT = '/dev/ttyUSB2' BAUDRATE = 9600 print('start main...') modem = GsmModem(PORT, BAUDRATE) modem.connect() print('before') print(modem.write('AT')) print('after')
def run(self): # Initialize the GPIO interface #exportpins() #writepins('1') logging.info("Modem thread running.") global modem global ppp_requested global sms_queue global beat global modem_failure rxListenLength = 5 init_count = 0 while self.running: beat += 1 while self.running and not ppp_requested and init_count > -1: if (init_count > 10): # Let's exit after 10 fails self.running = False modem_failure = True return(1) try: init_count = init_count + 1 modem = GsmModem(PORT, BAUDRATE, incomingCallCallbackFunc=handleIncomingCall, smsReceivedCallbackFunc=handleSms) logging.info("Initializing modem, try {0}.".format(init_count)) modem.connect(PIN) modem.write('AT+CFUN=1') init_count = -1 except (OSError, TimeoutException,CommandError): # OSError means pppd is likely running logging.error("Failed to initialize the GSM module.") try: modem.close() except AttributeError: True time.sleep(5) #self.modemPowerCycle() logging.info('Waiting for incoming calls...') while self.running and not ppp_requested and init_count < 0: try: #waitForNetworkCoverage() self.signalStrength = modem.signalStrength self.networkName = modem.networkName data['signalStrength'] = self.signalStrength data['networkName'] = self.networkName #modem.write("AT+CFUN=1") serving_cell=self.CGED_REGEX.match(modem.write("AT+CGED=3")[0]) if serving_cell: mcc=serving_cell.group(1) mnc=serving_cell.group(2) lac=serving_cell.group(3) ci=serving_cell.group(4) self.cellInfo="{0}/{1}/{2}/{3}".format(mcc, mnc, lac, ci) data['cellInfo'] = self.cellInfo # Comms are handled elsewhere so we could eventually just sleep, waiting #time.sleep(rxListenLength) if (self.signalStrength > 5): sent_position = 0 if sms_enabled: while (len(sms_queue) > 0): text=sms_queue.pop() if (text == 'position') and sent_position: logging.info('Not resending position in the same interval') elif (text == 'position'): send_position_via_sms(default_destination) sent_position = 1 else: try: modem.sendSms(default_destination, text, waitForDeliveryReport=False) except (CommandError, TimeoutException): sms_queue.append(text) else: logging.info('Waiting for better network coverage') modem.rxThread.join(rxListenLength) if self.do_shutdown: logging.warn('Disabling radio RX/TX.') modem.write('AT+CFUN=0') self.running = False modem.close() except (CommandError, InterruptedException, PinRequiredError, IncorrectPinError, TimeoutException): logging.error("rxThread died: {0}".format(sys.exc_info()[0])) modem.close() time.sleep(5) init_count = 0 # If PPP was requested, now it's the time if self.running and ppp_requested and self.signalStrength > 5 and init_count < 0: try: self.signalStrength = 101 logging.info('Launching PPP session.') if sms_enabled: while (len(sms_queue) > 0): logging.info('==== Sending PPP activation SMS =====') text=sms_queue.pop() try: modem.sendSms(default_destination, text, waitForDeliveryReport=False) time.sleep(1) except (CommandError, TimeoutException): sms_queue.append(text) #waitForNetworkCoverage() modem.close() logging.info("Modem interface closed.") rc = subprocess.check_output(['/usr/bin/timeout','250','/usr/bin/pon'], stderr=subprocess.STDOUT) logging.info('PPP ended: %s' % s) except subprocess.CalledProcessError as e: logging.info('PPP ended: %s' % e) sms_queue.append('PPP connection terminated') ppp_requested = False init_count = 0
def main(): args = parseArgsPy26( ) if sys.version_info[0] == 2 and sys.version_info[1] < 7 else parseArgs() print('args:', args) modem = GsmModem(args.port, args.baud) print('Connecting to GSM modem on {0}...'.format(args.port)) try: modem.connect(args.pin) except PinRequiredError: sys.stderr.write( 'Error: SIM card PIN required. Please specify a PIN with the -p argument.\n' ) sys.exit(1) except IncorrectPinError: sys.stderr.write('Error: Incorrect SIM card PIN entered.\n') sys.exit(1) if args.debug: # Print debug info print('\n== MODEM DEBUG INFORMATION ==\n') #print('ATI', modem.write('ATI', parseError=False)) print('AT+CGMI:', modem.write('AT+CGMI', parseError=False)) print('AT+CGMM:', modem.write('AT+CGMM', parseError=False)) print('AT+CGMR:', modem.write('AT+CGMR', parseError=False)) print('AT+CFUN=?:', modem.write('AT+CFUN=?', parseError=False)) print('AT+WIND=?:', modem.write('AT+WIND=?', parseError=False)) print('AT+WIND?:', modem.write('AT+WIND?', parseError=False)) print('AT+CPMS=?:', modem.write('AT+CPMS=?', parseError=False)) print('AT+CNMI=?:', modem.write('AT+CNMI=?', parseError=False)) print('AT+CVHU=?:', modem.write('AT+CVHU=?', parseError=False)) print('AT+CSMP?:', modem.write('AT+CSMP?', parseError=False)) print('AT+GCAP:', modem.write('AT+GCAP', parseError=False)) print('AT+CPIN?', modem.write('AT+CPIN?', parseError=False)) print('AT+CLAC:', modem.write('AT+CLAC', parseError=False)) print() else: # Print basic info print('\n== MODEM INFORMATION ==\n') print('Manufacturer:', modem.manufacturer) print('Model:', modem.model) print('Revision:', modem.revision if modem.revision != None else 'N/A') print('\nIMEI:', modem.imei if modem.imei != None else 'N/A') print('IMSI:', modem.imsi if modem.imsi != None else 'N/A') print('\nNetwork:', modem.networkName) print('Signal strength:', modem.signalStrength) print('\n\nATI;', modem.write('ATI', parseError=False)) print('AT+CGSN:', modem.write('AT+CGSN', parseError=False)) print('AT+CIMI:', modem.write('AT+CIMI', parseError=False)) print('AT+QCCID:', modem.write('AT+QCCID', parseError=False)) print('AT+QSPN:', modem.write('AT+QSPN', parseError=False)) print('AT+CSQ:', modem.write('AT+CSQ', parseError=False)) print('AT+QNWINFO:', modem.write('AT+QNWINFO', parseError=False)) print('AT+CSTT=?:', modem.write('AT+CSTT=?', parseError=False)) print('AT+CIFSR:', modem.write('AT+CIFSR', parseError=False)) addresses = [ i['addr'] for i in ifaddresses('wwan0').setdefault( AF_INET, [{ 'addr': 'No IP addr' }]) ] print('%s: %s' % ('wwan0', ', '.join(addresses))) print()
diachihc2['user'] = str(noidunghc2[vitri:noidunghc2.find(".", vitri)]) print(diachihc2['user']) except: diachihc2['user'] = '******' try: if "pass" in noidunghc2: vitri = noidunghc2.find("pass") + 5 diachihc2['password'] = str( noidunghc2[vitri:noidunghc2.find(".", vitri)]) print(diachihc2['password']) except: diachihc2['password'] = '******' hc2 = hc2.hc2(diachihc2['user'], diachihc2['password'], diachihc2['ip']) #hc2.setvariable('an_ninh','1') if __name__ == "__main__": modem.write('AT+CPBR=1') modem.write('AT+CPBR=2') modem.write('AT+CPBR=3') modem.write('AT+CPBR=4') modem.waitForNetworkCoverage(30) time.sleep(1) t = threading.Timer(30.0, kttaikhoan) t.start() try: modem.rxThread.join( 2**31 ) # Specify a (huge) timeout so that it essentially blocks indefinitely, but still receives CTRL+C interrupt signal finally: modem.close() sys.exit(app.exec_())