How to send long message using smpp.twisted python library.
I know how to send short message before 160 bytes.
For example:
ESME_NUM = '9090'
phone = '123456'
short_message = 'There is not short message.'*15
submit_pdu = SubmitSM(
source_addr=ESME_NUM,
destination_addr=phone,
short_message=short_message,
source_addr_ton=SOURCE_ADDR_TON,
dest_addr_ton=DEST_ADDR_TON,
dest_addr_npi=DEST_ADDR_NPI,
esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT),
protocol_id=0,
registered_delivery=RegisteredDelivery(
RegisteredDeliveryReceipt.SMSC_DELIVERY_RECEIPT_REQUESTED),
replace_if_present_flag=ReplaceIfPresentFlag.DO_NOT_REPLACE,
data_coding=DataCoding(DataCodingScheme.DEFAULT, DataCodingDefault.UCS2),
)
submitSMDeferred = smpp.sendDataRequest(submit_pdu)
If short_message > 160 b I cannot send message.
I found solution with using message_payload, but sms split on parts.
length = len(short_message)
splitat = 160
parts = length/splitat +1
submit_pdu = None
submitSMDeferred = defer.Deferred()
if length > splitat:
for k in range(parts):
msgpart = short_message[k*splitat:k*splitat+splitat]
self.logger.info('%s - %s - %s' % (msgpart, parts, k))
submit_pdu = SubmitSM(
source_addr=self.ESME_NUM,
destination_addr=source_addr,
source_addr_ton=self.SOURCE_ADDR_TON,
dest_addr_ton=self.DEST_ADDR_TON,
dest_addr_npi=self.DEST_ADDR_NPI,
esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT),
protocol_id=0,
registered_delivery=RegisteredDelivery(
RegisteredDeliveryReceipt.SMSC_DELIVERY_RECEIPT_REQUESTED),
replace_if_present_flag=ReplaceIfPresentFlag.DO_NOT_REPLACE,
data_coding=DataCoding(DataCodingScheme.DEFAULT, DataCodingDefault.UCS2),
sar_msg_ref_num = 1,
sar_total_segments = parts,
sar_segment_seqnum = k+1,
message_payload=msgpart
)
submitSMDeferred = smpp.sendDataRequest(submit_pdu)
I'm sorry. You just can use message_payload instead short_message.
Example:
ESME_NUM = '9090'
phone = '123456'
short_message = 'There is not short message.'*15
submit_pdu = SubmitSM(
source_addr=ESME_NUM,
destination_addr=phone,
message_payload=short_message,
source_addr_ton=SOURCE_ADDR_TON,
dest_addr_ton=DEST_ADDR_TON,
dest_addr_npi=DEST_ADDR_NPI,
esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT),
protocol_id=0,
registered_delivery=RegisteredDelivery(
RegisteredDeliveryReceipt.SMSC_DELIVERY_RECEIPT_REQUESTED),
replace_if_present_flag=ReplaceIfPresentFlag.DO_NOT_REPLACE,
data_coding=DataCoding(DataCodingScheme.DEFAULT, DataCodingDefault.UCS2),
)
smpp.sendDataRequest(submit_pdu).addBoth(message_sent)
Stay it here.
Related
I have 2 PLCs with serial port. one is mitsubishi Q00Jcpu mc protocol, another is omron hostlink protocol.
I tried to use python pyserial lib to write to the PLC and read response.
But failed, I tried to use a serial tool to test and got nice response,
serial tool success communicate with PLC, I read CIO address start 100 and size 2, it got 12345678, that is a true result.
my code :
import serial
omr = serial.Serial(port='COM4', baudrate=9600, timeout=0.5)
omr.parity=serial.PARITY_EVEN
omr.bytesize = 7
omr.stopbits =2
resp = omr.write(b'\x40\x30\x30\x46\x41\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x31\x30\x31\x42\x30\x30\x30\x36\x34\x30\x30\x30\x30\x30\x32\x30\x35\x2a\x0d')
print(resp) # print 34
resp = omr.write(b'#00FA0000000000101B0006400000205*\CR')
print(resp) # print 36
It seems return the len of write data, I tried both hex and ascii, all failed.
I figured it how, the return of serial.write is not the result. If need the response from device, should use read_until(), not sure weather this is a good way, please let me know if you have any suggestions.
Anyway, the class i make, can read the omron PLC by giving different params, hope it can help someone.
DEMO:
import serial
# cmd = '0101B00064000001'
class OMR_SERIAL_TOOL:
def __init__(self,port,baudrate):
self.omr = serial.Serial(port=port, baudrate=baudrate, timeout=0.5)
self.omr.parity=serial.PARITY_EVEN
self.omr.bytesize = 7
self.omr.stopbits =2
self.head ='#00FA000000000'
#staticmethod
def get_xor(frame):
res = ord(frame[0])
for i in frame[1:]:
res ^= ord(i)
res = str(res)
if len(res) == 1:
res = '0'+res
return res
def omr_read(self,head,cmd):
xor = OMR_SERIAL_TOOL.get_xor(head+cmd)
self.omr.write('{}{}{}*\r'.format(head,cmd,xor).encode())
resp = self.omr.read_until("\r".encode())
return str(resp[23:-4],encoding='utf-8')
test = OMR_SERIAL_TOOL('COM4',9600)
res = test.omr_read(test.head,cmd='0101B00064000002')
print(res) # 12345678 , which is the correct response
BOOM! VERSION 1.0
import serial
class OMR_SERIAL_TOOL:
def __init__(self,port,baudrate,mode):
self.omr = serial.Serial(port=port, baudrate=baudrate, timeout=0.5)
self.omr.parity=serial.PARITY_EVEN
self.omr.bytesize = 7
self.omr.stopbits =2
# fins mdoe
if mode == 'fins':
self.head ='#00FA000000000'
self.cmd_map = {
"MEMORY_AREA_READ":"0101",
"MEMORY_AREA_WRITE":"0102",
"MEMORY_AREA_FILL":"0103",
"MULTI_MEMORY_AREA_READ":"0104",
"MEMORY_AREA_TRANSFER":"0105"
}
# cs/cj mode
self.io_memory_area_code_map={
"CIO_bit":"30",
"WR_bit":"31",
"HR_bit":"32",
"AR_bit":"33",
"CIO_word":"B0",
"WR_word":"B1",
"HR_word":"B2",
"AR_word":"B3"
}
#staticmethod
def get_xor(frame):
res = ord(frame[0])
for i in frame[1:]:
res ^= ord(i)
res = str(res)
if len(res) == 1:
res = '0'+res
res = str(hex(int(res)))[2:]
upcase_res = ''
for i in res:
if i.isdigit():
upcase_res += i
elif i.isalpha():
upcase_res += i.upper()
if len(upcase_res) == 1:
upcase_res = '0'+upcase_res
return upcase_res
def omr_read(self,cmd,code,address,size):
address = str(hex(address))[2:]
size = str(hex(size))[2:]
while len(address) < 4:
address = '0' + address
while len(size) < 4:
size = '0' + size
frame = self.head+cmd+code+address+'00'+size
xor = OMR_SERIAL_TOOL.get_xor(frame)
#print(frame+xor)
self.omr.write('{}{}*\r'.format(frame,xor).encode())
resp = self.omr.read_until("\r".encode())
return str(resp[23:-4],encoding='utf-8')
omr_client = OMR_SERIAL_TOOL('COM4',9600,'fins')
cmd = omr_client.cmd_map['MEMORY_AREA_READ']
code = omr_client.io_memory_area_code_map['CIO_word']
res = omr_client.omr_read(cmd,code,address=500,size=1)
I tested it good on CIO read, please let me know if you find any bugs.
I have a Django application where I am trying to make a call to Fedex's API to send out a shipping label for people wanting to send in a product for cash. When I try to make the call though it says there is a data validation issue with the Expiration field in the XML I am filling out. I swear this has worked in the past with me formatting the date as "YYYY-MM-DD", but now it is not. I read that with Fedex, you need to format the date as ISO, but that is also not passing the data validation. I am using a python package created to help with tapping Fedex's API.
Django view function for sending API Call
def Fedex(request, quote):
label_link = ''
expiration_date = datetime.datetime.now() + datetime.timedelta(days=10)
# formatted_date = "%s-%s-%s" % (expiration_date.year, expiration_date.month, expiration_date.day)
formatted_date = expiration_date.replace(microsecond=0).isoformat()
if quote.device_type != 'laptop':
box_length = 9
box_width = 12
box_height = 3
else:
box_length = 12
box_width = 14
box_height = 3
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
## Page 411 of FedEx Dev Guide - 20.14 Email Labels
CONFIG_OBJ = FedexConfig(key=settings.FEDEX_KEY, password=settings.FEDEX_PASSWORD, account_number=settings.FEDEX_ACCOUNT,
meter_number=settings.FEDEX_METER, use_test_server=settings.USE_FEDEX_TEST)
fxreq = FedexCreatePendingShipRequestEmail(CONFIG_OBJ, customer_transaction_id='xxxxxx id:01')
fxreq.RequestedShipment.ServiceType = 'FEDEX_GROUND'
fxreq.RequestedShipment.PackagingType = 'YOUR_PACKAGING'
fxreq.RequestedShipment.DropoffType = 'REGULAR_PICKUP'
fxreq.RequestedShipment.ShipTimestamp = datetime.datetime.now()
# Special fields for the email label
fxreq.RequestedShipment.SpecialServicesRequested.SpecialServiceTypes = ('RETURN_SHIPMENT', 'PENDING_SHIPMENT')
fxreq.RequestedShipment.SpecialServicesRequested.PendingShipmentDetail.Type = 'EMAIL'
fxreq.RequestedShipment.SpecialServicesRequested.PendingShipmentDetail.ExpirationDate = formatted_date
email_address = fxreq.create_wsdl_object_of_type('EMailRecipient')
email_address.EmailAddress = quote.email
email_address.Role = 'SHIPMENT_COMPLETOR'
# RETURN SHIPMENT DETAIL
fxreq.RequestedShipment.SpecialServicesRequested.ReturnShipmentDetail.ReturnType = ('PENDING')
fxreq.RequestedShipment.SpecialServicesRequested.ReturnShipmentDetail.ReturnEMailDetail = fxreq.create_wsdl_object_of_type(
'ReturnEMailDetail')
fxreq.RequestedShipment.SpecialServicesRequested.ReturnShipmentDetail.ReturnEMailDetail.MerchantPhoneNumber = 'x-xxx-xxx-xxxx'
fxreq.RequestedShipment.SpecialServicesRequested.PendingShipmentDetail.EmailLabelDetail.Recipients = [email_address]
fxreq.RequestedShipment.SpecialServicesRequested.PendingShipmentDetail.EmailLabelDetail.Message = "Xxxxxx Xxxxxx"
fxreq.RequestedShipment.LabelSpecification = {'LabelFormatType': 'COMMON2D', 'ImageType': 'PDF'}
fxreq.RequestedShipment.Shipper.Contact.PersonName = quote.first_name + ' ' + quote.last_name
fxreq.RequestedShipment.Shipper.Contact.CompanyName = ""
fxreq.RequestedShipment.Shipper.Contact.PhoneNumber = quote.phone
fxreq.RequestedShipment.Shipper.Address.StreetLines.append(quote.address)
fxreq.RequestedShipment.Shipper.Address.City = quote.city
fxreq.RequestedShipment.Shipper.Address.StateOrProvinceCode = quote.state
fxreq.RequestedShipment.Shipper.Address.PostalCode = quote.zip
fxreq.RequestedShipment.Shipper.Address.CountryCode = settings.FEDEX_COUNTRY_CODE
fxreq.RequestedShipment.Recipient.Contact.PhoneNumber = settings.FEDEX_PHONE_NUMBER
fxreq.RequestedShipment.Recipient.Address.StreetLines = settings.FEDEX_STREET_LINES
fxreq.RequestedShipment.Recipient.Address.City = settings.FEDEX_CITY
fxreq.RequestedShipment.Recipient.Address.StateOrProvinceCode = settings.FEDEX_STATE_OR_PROVINCE_CODE
fxreq.RequestedShipment.Recipient.Address.PostalCode = settings.FEDEX_POSTAL_CODE
fxreq.RequestedShipment.Recipient.Address.CountryCode = settings.FEDEX_COUNTRY_CODE
fxreq.RequestedShipment.Recipient.AccountNumber = settings.FEDEX_ACCOUNT
fxreq.RequestedShipment.Recipient.Contact.PersonName = ''
fxreq.RequestedShipment.Recipient.Contact.CompanyName = 'Xxxxxx Xxxxxx'
fxreq.RequestedShipment.Recipient.Contact.EMailAddress = 'xxxxxx#xxxxxxxxx'
# Details of Person Who is Paying for the Shipping
fxreq.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = settings.FEDEX_ACCOUNT
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Contact.PersonName = 'Xxxxx Xxxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Contact.CompanyName = 'Xxxxx Xxxxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Contact.PhoneNumber = 'x-xxx-xxx-xxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Contact.EMailAddress = 'xxxxxxx#xxxxxxxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.StreetLines = 'Xxxxx N. xXxxxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.City = 'Xxxxxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.StateOrProvinceCode = 'XX'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.PostalCode = 'xxxxx'
fxreq.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.CountryCode = 'US'
# Package Info
package1 = fxreq.create_wsdl_object_of_type('RequestedPackageLineItem')
package1.SequenceNumber = '1'
package1.Weight.Value = 1
package1.Weight.Units = "LB"
package1.Dimensions.Length = box_length
package1.Dimensions.Width = box_width
package1.Dimensions.Height = box_height
package1.Dimensions.Units = "IN"
package1.ItemDescription = 'Phone'
fxreq.RequestedShipment.RequestedPackageLineItems.append(package1)
fxreq.RequestedShipment.PackageCount = '1'
try:
fxreq.send_request()
label_link = str(fxreq.response.CompletedShipmentDetail.AccessDetail.AccessorDetails[0].EmailLabelUrl)
except Exception as exc:
print('Fedex Error')
print('===========')
print(exc)
print('==========')
return label_link
Error Log
Error:cvc-datatype-valid.1.2.1: \\'2017-11-3\\' is not a valid value for \\'date\\'.\\ncvc-type.3.1.3: The value \\'2017-11-3\\' of element \\'ns0:ExpirationDate\\' is not valid."\\n }\\n }' (Error code: -1)
Through this code I've update a bunch of rows in Google Spreadsheet.
The request goes well and returns me the updatedRange below.
result = service.spreadsheets().values().append(
spreadsheetId=spreadsheetId,
range=rangeName,
valueInputOption="RAW",
insertDataOption="INSERT_ROWS",
body=body
).execute()
print(result)
print("Range updated")
updateRange = result['updates']['updatedRange']
Now I would like to do a batchUpdate request to set the formatting or set a protected range, but those API require a range specified as startRowIndex, endRowIndex and so on.
How could I retrieve the rows index from the updatedRange?
Waiting for a native or better answer, I'll post a function I've created to translate a namedRange into a gridRange.
The function is far from perfect and does not translate the sheet name to a sheet id (I left that task to another specific function), but accept named ranges in the form:
sheet!A:B
sheet!A1:B
sheet!A:B5
sheet!A1:B5
Here is the code
import re
def namedRange2Grid(self, rangeName):
ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
match = re.match(".*?\!([A-Z0-9]+)\:([A-Z0-9]+)", rangeName)
if match:
start = match.group(1)
end = match.group(2)
matchStart = re.match("([A-Z]{1,})([1-9]+){0,}", start)
matchEnd = re.match("([A-Z]{1,})([1-9]+){0,}", end)
if matchStart and matchEnd:
GridRange = {}
letterStart = matchStart.group(1)
letterEnd = matchEnd.group(1)
if matchStart.group(2):
numberStart = int(matchStart.group(2))
GridRange['startRowIndex'] = numberStart - 1
if matchEnd.group(2):
numberEnd = int(matchEnd.group(2))
GridRange['endRowIndex'] = numberEnd
i = 0
for l in range(0, len(letterStart)):
i = i + (l * len(ascii_uppercase))
i = i + ascii_uppercase.index(letterStart[l])
GridRange['startColumnIndex'] = i
i = 0
for l in range(0, len(letterEnd)):
i = i + (l * len(ascii_uppercase))
i = i + ascii_uppercase.index(letterEnd[l])
GridRange['endColumnIndex'] = i + 1
return GridRange
I am working on parsing a number of large files and want to be sure I'm doing it as efficiently as possible. One of the lines I am parsing looks like this (a Windows Security Event Log 4624):
Security/Microsoft-Windows-Security-Auditing ID [4624] :EventData/Data -> SubjectUserSid = S-1-0-0 SubjectUserName = - SubjectDomainName = - SubjectLogonId = 0x0000000000000000 TargetUserSid = S-1-1-11-1111111111-1111111111-1111111111-1111 TargetUserName = johndoe TargetDomainName = TestDomain TargetLogonId = 0x0000000001111111 LogonType = 3 LogonProcessName = NtLmSsp AuthenticationPackageName = NTLM WorkstationName = TestWorkstation LogonGuid = {00000000-0000-0000-0000-000000000000} TransmittedServices = - LmPackageName = NTLM V2 KeyLength = 128 ProcessId = 0x0000000000000000 ProcessName = - IpAddress = 1.1.1.1 IpPort = 11111
What I want to know is, what is the most efficient way to pull multiple fields from that line? I could partition the line repeatedly until I reach each field I am interested in, but I feel like repeatedly looping over the line is a waste of time/resources.
Is there an intelligent way to look at the line only once but pull out, for example, the following fields:
LogonType = 3
TargetUserName = johndoe
TargetUserSid = S-1-1-11-1111111111-1111111111-1111111111-1111
As an example, what I could do is repeat the following process:
part = line.partition('TargetUserName = ')[2]
username = part.partition(' ')[0]
to get each field that I want (the above example getting me just the username), but again that feels inefficient to me.
Is there a better way to handle it?
Each field name is a group of uppercase and lowercase characters. They are separated from their values by =. Each value is a group of non-whitespace characters. You can use re.findall with matching groups to locate all "letters = nonwhitespace" instances. This will give you a list of tuples, which you can either save or iterate through and pass to a format string:
>>> s = '''Security/Microsoft-Windows-Security-Auditing ID [4624] :EventData/Data -> SubjectUserSid = S-1-0-0 SubjectUserName = - SubjectDomainName = - SubjectLogonId = 0x0000000000000000 TargetUserSid = S-1-1-11-1111111111-1111111111-1111111111-1111 TargetUserName = johndoe TargetDomainName = TestDomain TargetLogonId = 0x0000000001111111 LogonType = 3 LogonProcessName = NtLmSsp AuthenticationPackageName = NTLM WorkstationName = TestWorkstation LogonGuid = {00000000-0000-0000-0000-000000000000} TransmittedServices = - LmPackageName = NTLM V2 KeyLength = 128 ProcessId = 0x0000000000000000 ProcessName = - IpAddress = 1.1.1.1 IpPort = 11111 '''
>>> import re
>>> for item in re.findall(r'([A-Za-z]+) = (\S+)', s):
... print('{} = {}'.format(*item))
...
SubjectUserSid = S-1-0-0
SubjectUserName = -
SubjectDomainName = -
SubjectLogonId = 0x0000000000000000
TargetUserSid = S-1-1-11-1111111111-1111111111-1111111111-1111
TargetUserName = johndoe
TargetDomainName = TestDomain
TargetLogonId = 0x0000000001111111
LogonType = 3
LogonProcessName = NtLmSsp
AuthenticationPackageName = NTLM
WorkstationName = TestWorkstation
LogonGuid = {00000000-0000-0000-0000-000000000000}
TransmittedServices = -
LmPackageName = NTLM
KeyLength = 128
ProcessId = 0x0000000000000000
ProcessName = -
IpAddress = 1.1.1.1
IpPort = 11111
You can also turn it into a dictionary for easy access:
>>> d = dict(re.findall(r'([A-Za-z]+) = (\S+)', s))
>>> d['LogonType']
'3'
st = 'Security/Microsoft-Windows-Security-Auditing ID [4624] :EventData/Data -> SubjectUserSid = S-1-0-0 SubjectUserName = - SubjectDomainName = - SubjectLogonId = 0x0000000000000000 TargetUserSid = S-1-1-11-1111111111-1111111111-1111111111-1111 TargetUserName = johndoe TargetDomainName = TestDomain TargetLogonId = 0x0000000001111111 LogonType = 3 LogonProcessName = NtLmSsp AuthenticationPackageName = NTLM WorkstationName = TestWorkstation LogonGuid = {00000000-0000-0000-0000-000000000000} TransmittedServices = - LmPackageName = NTLM V2 KeyLength = 128 ProcessId = 0x0000000000000000 ProcessName = - IpAddress = 1.1.1.1 IpPort = 11111';
using re module and re.findall you can I think get want you want
import re
li = re.findall(r'LogonType\s*=\s*\d+|TargetUserName\s*=\s*\w+|TargetUserSid\s*=\s*\w-.*?\s',st,re.MULTILINE| re.DOTALL)
>>>li
['TargetUserSid = S-1-1-11-1111111111-1111111111-1111111111-1111 ', 'TargetUserName = johndoe', 'LogonType = 3']
I am trying to convert a group of IP ranges that can start and end on any given address, but not necessarily on a .0, .127, or .255, etc. I have code that is mostly working; however, it can be slow for large ranges.
For example find_range("1.40.0.0","1.44.255.255") will take over a minute to return the correct result of 1.40.0.0/14 and 1.44.0.0/16.
Also, I am have trouble when the starting range does not end with a .0. How can I fix these 2 issues: slowness on large IP ranges and when the starting range does not end in .0?
For the slowness problem, I tried skipping more than 1 address at a time, but then this would miss smaller ranges.
import ipaddress, socket, struct
def ip2int(addr):
return struct.unpack("!I", socket.inet_aton(addr))[0]
def int2ip(addr):
return socket.inet_ntoa(struct.pack("!I", addr))
def ipminus(ip, amount=1):
tmp = ip2int(ip)
return int2ip(tmp - amount)
def ipplus(ip):
tmp = ip2int(ip)
return int2ip(tmp + 1)
def cidr_notation(a,b):
for mask in range(32, 6, -1):
test = "%s/%s" % (a,mask)
try:
n = ipaddress.IPv4Network(test,False)
if b == "%s" % (n.broadcast_address):
return test
except:
pass
return None
def split_range(a,b):
a1 = ip2int(a)
b1 = ip2int(b)
needed = 1
while needed:
result = cidr_notation(a,b)
if result:
print( "* %16s\t%16s\t%16s" % (result, a, b))
if ip2int(b) > b1:
needed = 0
else:
a = ipplus(b)
b = int2ip(b1)
else:
b = ipminus(b)
return result
def find_range(x,y):
result = cidr_notation(x,y)
if result:
print( "# %16s\t%16s\t%16s" % (result, x, y))
else:
split_range(x,y)
# main...
print("%16s\t%16s\t%16s" % ("mask","start","end"))
print("%16s\t%16s\t%16s" % ("----","-----","---"))
find_range("128.191.0.0","128.191.255.255") #fast
find_range("10.55.96.106","10.55.96.106") #fast
find_range("5.135.14.0","5.135.61.11") #slow
find_range("4.31.64.72","4.59.175.255") #does not work, how to fix?
find_range("1.40.0.0","1.44.255.255") #very slow
# 5000 more find_range() calls...
Based on bsdlp's comment, this code got a lot simpler and faster!
def find_range(x,y,c_code="",c_name=""):
print()
print("%29s\t%23s" % (x,y))
print("%16s\t%16s\t%16s\t%4s\t%s" % ("mask","start","end","code","name"))
print("%16s\t%16s\t%16s\t%4s\t%s" % ("----","-----","---","----","----"))
result = ipaddress.summarize_address_range( ipaddress.IPv4Address(x), ipaddress.IPv4Address(y) )
for entry in result:
net = str( entry.network_address )
bcast = str( entry.broadcast_address )
print( "%16s\t%16s\t%16s\t%4s\t%s" % (entry, net, bcast,c_code,c_name))