From 6f829d2f009e77e5740048a97f0aec8d02342146 Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Fri, 6 Apr 2012 18:20:58 -0300 Subject: [PATCH 1/7] Total redesign of the smpp_parts to be used as properties in the top level objects The code is a bit obscure, but if some time it could be figure out --- src/smpp_const.py | 78 ++++++++++++++ src/smpp_parts.py | 262 +++++++++++++++++++--------------------------- 2 files changed, 186 insertions(+), 154 deletions(-) diff --git a/src/smpp_const.py b/src/smpp_const.py index 1e493ca..8bf5ce3 100644 --- a/src/smpp_const.py +++ b/src/smpp_const.py @@ -123,4 +123,82 @@ ITS_REPLY_TYPE = '1380' ITS_SESSION_INFO = '1383' +command_id = ( + '80000000', + '00000001', + '80000001', + '00000002', + '80000002', + '00000003', + '80000003', + '00000004', + '80000004', + '00000005', + '80000005', + '00000006', + '80000006', + '00000007', + '80000007', + '00000008', + '80000008', + '00000009', + '80000009', + '0000000b', + '00000015', + '80000015', + '00000021', + '80000021', + '00000102', + '00000103', + '80000103') + + + command_status = ( '00000000', + '00000001', + '00000002', + '00000003', + '00000004', + '00000005', + '00000006', + '00000007', + '00000008', + '0000000a', + '0000000b', + '0000000c', + '0000000d', + '0000000e', + '0000000f', + '00000011', + '00000013', + '00000014', + '00000015', + '00000033', + '00000034', + '00000040', + '00000042', + '00000043', + '00000044', + '00000045', + '00000048', + '00000049', + '00000050', + '00000051', + '00000053', + '00000054', + '00000055', + '00000058', + '00000061', + '00000062', + '00000063', + '00000064', + '00000065', + '00000066', + '00000067', + '000000c0', + '000000c1', + '000000c2', + '000000c3', + '000000c4', + '000000fe', + '000000ff') diff --git a/src/smpp_parts.py b/src/smpp_parts.py index bc5e93e..2464f86 100644 --- a/src/smpp_parts.py +++ b/src/smpp_parts.py @@ -1,79 +1,58 @@ import smpp_const +import functools -class CommandLength(object): - def __call__(self, param_order): - return hex(sum([len(i) for i in param_order])+16).replace('0x', '').zfill(8) +def command_length(param_order): + return hex(sum([len(i) for i in param_order])+16).replace('0x', '').zfill(8) -class CommandID(object): - #Must check if is a valid command_id - def __init__(self, value): - self._value = value - - def __call__(self, value = None): - if value == None: - return self._value - else: - self._value = value - -class CommandStatus(object): - #Must check if is a valid command_status - def __init__(self, value): - self._value = value - - def __call__(self, value = None): - if value == None: - return self._value - else: - self._value = value +def generic_value_check(values, value): + if value in values: + return value + + else: + raise ValueError + +command_id = functools.partial(generic_value_check, part.command_id) +command_status = functools.partial(generic_value_check, part.command_status) + +def sequence_number(value): + return hex(value).replace('0x', '').zfill(8) -class SequenceNumber(object): - def __init__(self, value): - self._value = hex(value).replace('0x', '').zfill(8) - - def __call__(self, value = None): - if value == None: - return self._value - else: - self._value = hex(value).replace('0x', '').zfill(8) - -class Parameter(object): - def __init__(self, type_, value, max_size, min_size = 0): - self.type = type_ - self.max_size = max_size - self.min_size = min_size - self.set_value = {'string':self._string_parser, - 'int':self._int_parser, - 'bit':self._bit_parser}.get(type_) - self.set_value(value) - - def _string_parser(self, value): - self._value = value.encode('hex') - - if len(self._value) > self.max_size: - raise ValueError(self.__class__.__name__+' cannot exceed '+str(self.max_size)+' characters') - elif len(self._value) < self.min_size: - raise ValueError(self.__class__.__name__+' cannot be less than '+str(self.max_size)+' characters') - self._value = '%s00' % (self._value) - - def _int_parser(self, value): - self._value = hex(value).replace('0x', '').zfill(2) - if len(self._value) > self.max_size: - raise ValueError(self.__class__.__name__+' cannot exceed 255 as value (00 - ff)') - - def _bit_parser(self, value): - self._value = value.zfill(2) - if self._value not in ('00', '01', '10', '11'): - raise ValueError(self.__class__.__name__+' Bit mask wrong value') - - def __len__(self): - return len(self._value)/2 - - def __call__(self, value = None): - if value == None: - return self._value - else: - self.set_value(value) +def set_string_parameter(max_size, min_size, name, self, value): + value = value.encode('hex') + + if len(value) > max_size: + raise ValueError('Cannot exceed %s characters' % (max_size)) + + elif len(value) < min_size: + raise ValueError('Cannot be less than %s characters' % (min_size)) + + setattr(self, name, '%s00' % (value)) + +def get_string_parameter(name, self): + return getattr(self, name).decode('hex') + +def set_int_parameter(max_size, name, self, value): + value = hex(value).replace('0x', '').zfill(2) + if len(value) > max_size: + raise ValueError('Cannot exceed 255 as value (00 - ff): %s' % (value)) + + setattr(self, name, value) + +def get_int_parameter(name, self): + return int(getattr(self, name), 16) + + +def set_bit_parameter(max_size, name, self, value): + value = value.zfill(2) + if value not in ('00', '01', '10', '11'): + raise ValueError('Bit mask wrong value: %s' % (value)) + + setattr(self, name, value) + +def get_bit_parameter(name, self): + return getattr(self, name) + class IntParameter(Parameter): def __init__(self, value): @@ -103,91 +82,66 @@ def __call__(self, value = None): self.value(value) self.length = len(self.value) - -class SystemID(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 32) - -class Password(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 18) - -class SystemType(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 26) - -class InterfaceVersion(IntParameter): - pass - -class AddrTon(IntParameter): - pass +#To be used as properties to build the top objects +#I know looks bizarre... but will avoid a lot code to be done +#I know: +#Beautiful is better than ugly. +#Explicit is better than implicit. +#Simple is better than complex. +#Complex is better than complicated. +set_system_id = functools.partial(set_string_parameter, 32, 0, '_system_id') +set_password = functools.partial(set_string_parameter, 18, 0, '_password') +set_system_type = functools.partial(set_string_parameter, 26, 0, '_system_type') +set_interface_version = functools.partial(set_int_parameter, 2, '_interface_version') +set_addr_ton = functools.partial(set_int_parameter, 2, '_addr_ton') +set_addr_npi = functools.partial(set_int_parameter, 2, '_addr_npi') +set_address_range = functools.partial(set_string_parameter, 82, 0, '_address_range') +set_service_type = functools.partial(set_string_parameter, 12, 0, '_service_type') +set_source_addr_ton = functools.partial(set_int_parameter, 2, '_source_addr_ton') +set_source_addr_npi = functools.partial(set_int_parameter, 2, '_source_addr_npi') +set_source_addr = functools.partial(set_string_parameter, 42, 0, '_source_addr') +set_dest_addr_ton = functools.partial(set_int_parameter, 2, '_dest_addr_ton') +set_dest_addr_npi = functools.partial(set_int_parameter, 2, '_dest_addr_npi') +set_dest_addr = functools.partial(set_string_parameter, 42, 0, '_dest_add') +set_esm_class = functools.partial(set_int_parameter, 2, '_esm_class') +set_protocol_id = functools.partial(set_int_parameter, 2, '_protocol_id') +set_priority_flag = functools.partial(set_int_parameter, 2, '_priority_flag') +set_schedule_delivery_time = functools.partial(set_string_parameter, 34, 2, '_schedule_delivery_time') +set_validity_period = functools.partial(set_string_parameter, 34, 2, '_validity_period') +set_registered_delivery = functools.partial(set_int_parameter, 2, '_registered_delivery') +set_replace_if_present_flag = functools.partial(set_int_parameter, 2, '_replace_if_present_flag') +set_data_coding = functools.partial(set_int_parameter, 2, '_data_coding') +set_sm_default_msg_id = functools.partial(set_int_parameter, 2, '_sm_default_msg_id') +set_sm_length = functools.partial(set_int_parameter, 2, '_sm_length') +set_short_message = functools.partial(set_string_parameter, 508, 0, '_short_message') + +get_system_id = functools.partial(get_string_parameter, '_system_id') +get_password = functools.partial(get_string_parameter, '_password') +get_system_type = functools.partial(get_string_parameter,'_system_type') +get_interface_version = functools.partial(get_int_parameter,'_interface_version') +get_addr_ton = functools.partial(get_int_parameter, '_addr_ton') +get_addr_npi = functools.partial(get_int_parameter, '_addr_npi') +get_address_range = functools.partial(get_string_parameter, '_address_range') +get_service_type = functools.partial(get_string_parameter, '_service_type') +get_source_addr_ton = functools.partial(get_int_parameter, '_source_addr_ton') +get_source_addr_npi = functools.partial(get_int_parameter, '_source_addr_npi') +get_source_addr = functools.partial(get_string_parameter, '_source_addr') +get_dest_addr_ton = functools.partial(get_int_parameter, '_dest_addr_ton') +get_dest_addr_npi = functools.partial(get_int_parameter, '_dest_addr_npi') +get_dest_addr = functools.partial(get_string_parameter, '_dest_add') +get_esm_class = functools.partial(get_int_parameter, '_esm_class') +get_protocol_id = functools.partial(get_int_parameter, '_protocol_id') +get_priority_flag = functools.partial(get_int_parameter, '_priority_flag') +get_schedule_delivery_time = functools.partial(get_string_parameter, '_schedule_delivery_time') +get_validity_period = functools.partial(get_string_parameter, '_validity_period') +get_registered_delivery = functools.partial(get_int_parameter, '_registered_delivery') +get_replace_if_present_flag = functools.partial(get_int_parameter, '_replace_if_present_flag') +get_data_coding = functools.partial(get_int_parameter, '_data_coding') +get_sm_default_msg_id = functools.partial(get_int_parameter, '_sm_default_msg_id') +get_sm_length = functools.partial(get_int_parameter, '_sm_length') +get_short_message = functools.partial(get_string_parameter, '_short_message') -class AddrNpi(IntParameter): - pass - -class AddressRange(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 82) - -class ServiceType(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 12) - -class SourceAddrTon(IntParameter): - pass - -class SourceAddrNpi(IntParameter): - pass - -class SourceAddr(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 42) -class DestAddrTon(IntParameter): - pass - -class DestAddrNpi(IntParameter): - pass - -class DestinationAddr(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 42) - -class EsmClass(IntParameter): - pass - -class ProtocolID(IntParameter): - pass - -class PriorityFlag(IntParameter): - pass - -class ScheduleDeliveryTime(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 34, min_size = 2) - -class ValidityPeriod(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 34, min_size = 2) - -class RegisteredDelivery(IntParameter): - pass - -class ReplaceIfPresentFlag(IntParameter): - pass - -class DataCoding(IntParameter): - pass - -class SmDefaultMsgID(IntParameter): - pass - -class SmLength(IntParameter): - pass - -class ShortMessage(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'string', value, 508) class DestAddrSubunit(TLV): def __init__(self, value): From 69e79e2af20dd66d8e993bf43dd60e68a7dbe157 Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Sat, 7 Apr 2012 08:39:05 -0300 Subject: [PATCH 2/7] Created all the standard parameters as properties --- src/smpp_parts.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/smpp_parts.py b/src/smpp_parts.py index 2464f86..46a80f2 100644 --- a/src/smpp_parts.py +++ b/src/smpp_parts.py @@ -1,23 +1,29 @@ import smpp_const import functools - -def command_length(param_order): - return hex(sum([len(i) for i in param_order])+16).replace('0x', '').zfill(8) -def generic_value_check(values, value): +def set_command_length(self, param_order): + self._command_length = hex(sum([len(i) for i in param_order]) + 16).replace('0x', '').zfill(8) + +def get_command_length(self): + return int(self._command_length, 16) + +def generic_value_check(values, name, self, value): if value in values: - return value + setattr(self, name, value) else: raise ValueError -command_id = functools.partial(generic_value_check, part.command_id) -command_status = functools.partial(generic_value_check, part.command_status) +command_id = functools.partial(generic_value_check, part.command_id, '_command_id') +command_status = functools.partial(generic_value_check, part.command_status, '_command_status') + +def set_sequence_number(self, value): + self._sequence_number = hex(value).replace('0x', '').zfill(8) + +def get_sequence_number(self) + return int(self._sequence_number, 16) -def sequence_number(value): - return hex(value).replace('0x', '').zfill(8) - def set_string_parameter(max_size, min_size, name, self, value): value = value.encode('hex') @@ -30,7 +36,7 @@ def set_string_parameter(max_size, min_size, name, self, value): setattr(self, name, '%s00' % (value)) def get_string_parameter(name, self): - return getattr(self, name).decode('hex') + return getattr(self, name)[:-2].decode('hex') def set_int_parameter(max_size, name, self, value): value = hex(value).replace('0x', '').zfill(2) @@ -54,10 +60,6 @@ def get_bit_parameter(name, self): return getattr(self, name) -class IntParameter(Parameter): - def __init__(self, value): - Parameter.__init__(self, 'int', value, 2) - class TLV(object): def __init__(self, parameter_tag, type_, value, max_size, min_size = 0): From 26acf575b2fe3c505ad2b3f1531f1fcbff765e81 Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Sun, 8 Apr 2012 10:57:35 -0300 Subject: [PATCH 3/7] Mandatory parameters done, except for the command_len and the sm_len. Started to port the smpp_operations from old to new model. Included the c-octet-string and the octet-string. --- src/smpp_const.py | 2 +- src/smpp_operation.py | 38 +++++++- src/smpp_parts.py | 208 ++++++++++++++++++++++++------------------ 3 files changed, 155 insertions(+), 93 deletions(-) diff --git a/src/smpp_const.py b/src/smpp_const.py index 8bf5ce3..aa036a0 100644 --- a/src/smpp_const.py +++ b/src/smpp_const.py @@ -154,7 +154,7 @@ - command_status = ( '00000000', +command_status = ( '00000000', '00000001', '00000002', '00000003', diff --git a/src/smpp_operation.py b/src/smpp_operation.py index 71863ea..5246644 100644 --- a/src/smpp_operation.py +++ b/src/smpp_operation.py @@ -14,7 +14,7 @@ def __init__(self, command_id = None, self.sequence_number = part.SequenceNumber(sequence_number) self.body = [] self.optional_parameter = [] - + def format_message(self): message = '' full_body = self.body[:] @@ -33,7 +33,41 @@ def format_message(self): return message - +class BindTransmitter(object): + __parameters = ['_command_length', '_command_id', '_command_status', + '_sequence_number', '_system_id', '_password', + '_system_type', '_interface_version', '_addr_ton', + '_addr_npi', '_address_range'] + + __optional_parameters = [] + + __slots__ = __parameters + __optional_parameters + + def __init__(self, **kargs): + self.command_id = smpp_const.BIND_TRANSMITTER + self.command_status = smpp_const.ESME_ROK + self.sequence_number = kargs.get('sequence_number') + self.system_id = kargs.get('system_id') + self.password = kargs.get('password') + self.system_type = kargs.get('system_type') + self.interface_version = kargs.get('interface_version') + self.addr_ton = kargs.get('addr_ton') + self.addr_npi = kargs.get('addr_npi') + self.address_range = kargs.get('address_range') + self.command_length = kargs.get('command_length', self.__slots__) + + command_length = property(part.get_command_length, part.set_command_length) + command_id = property(part.get_command_id, part.set_command_id) + command_status = property(part.get_command_status, part.set_command_status) + sequence_number = property(part.get_sequence_number, part.set_sequence_number) + system_id = property(part.get_system_id, part.set_system_id) + password = property(part.get_password, part.set_password) + system_type = property(part.get_system_type, part.set_system_type) + interface_version = property(part.get_interface_version, part.set_interface_version) + addr_ton = property(part.get_addr_ton, part.set_addr_ton) + addr_npi = property(part.get_addr_npi, part.set_addr_npi) + address_range = property(part.get_address_range, part.set_address_range) + class BindTransmitter(Header): def __init__(self, sequence_numb, system_id = '', password = '', system_type = '', interface_version = 52, diff --git a/src/smpp_parts.py b/src/smpp_parts.py index 46a80f2..0098803 100644 --- a/src/smpp_parts.py +++ b/src/smpp_parts.py @@ -1,54 +1,67 @@ -import smpp_const +import smpp_const as const import functools +def smpp_values_validation(name, value): + try: + if value in getattr(const, name[1:]): + return True -def set_command_length(self, param_order): - self._command_length = hex(sum([len(i) for i in param_order]) + 16).replace('0x', '').zfill(8) + else: + return False -def get_command_length(self): - return int(self._command_length, 16) + except AttributeError: + #if there is no validator, any value is possible + return True -def generic_value_check(values, name, self, value): - if value in values: - setattr(self, name, value) +def set_string_parameter(max_size, min_size, default_value, type_, name, self, value): + if value is None: + value = default_value - else: - raise ValueError + value = value.encode('hex') -command_id = functools.partial(generic_value_check, part.command_id, '_command_id') -command_status = functools.partial(generic_value_check, part.command_status, '_command_status') + if len(value) > max_size: + raise ValueError('Cannot exceed %s characters' % (max_size/2)) -def set_sequence_number(self, value): - self._sequence_number = hex(value).replace('0x', '').zfill(8) + elif len(value) < min_size: + raise ValueError('Cannot be less than %s characters' % (min_size/2)) -def get_sequence_number(self) - return int(self._sequence_number, 16) + elif not smpp_values_validation(name, value): + raise ValueError('%s is not a valid value for %s' % (value, name)) -def set_string_parameter(max_size, min_size, name, self, value): - value = value.encode('hex') + if type_ == 'c-octet_string': + setattr(self, name, '%s00' % (value)) - if len(value) > max_size: - raise ValueError('Cannot exceed %s characters' % (max_size)) + elif type_ == 'octet_string': + setattr(self, name, value) - elif len(value) < min_size: - raise ValueError('Cannot be less than %s characters' % (min_size)) +def get_string_parameter(name, type_, self): + value = '' + + if type_ == 'c-octet_string': + value = getattr(self, name)[:-2].decode('hex') + + elif type_ == 'octet_string': + value = getattr(self, name).decode('hex') + + return value - setattr(self, name, '%s00' % (value)) +def set_int_parameter(max_size, default_value, name, self, value): + if value is None: + value = default_value -def get_string_parameter(name, self): - return getattr(self, name)[:-2].decode('hex') + value = hex(value).replace('0x', '').zfill(max_size) -def set_int_parameter(max_size, name, self, value): - value = hex(value).replace('0x', '').zfill(2) if len(value) > max_size: - raise ValueError('Cannot exceed 255 as value (00 - ff): %s' % (value)) + raise ValueError('Cannot exceed %s: %s' % (max_size, value)) + + elif not smpp_values_validation(name, value): + raise ValueError('%s is not a valid value for %s' % (value, name)) setattr(self, name, value) def get_int_parameter(name, self): return int(getattr(self, name), 16) - def set_bit_parameter(max_size, name, self, value): value = value.zfill(2) if value not in ('00', '01', '10', '11'): @@ -60,30 +73,6 @@ def get_bit_parameter(name, self): return getattr(self, name) -class TLV(object): - def __init__(self, parameter_tag, type_, value, max_size, min_size = 0): - - self.parameter_tag = parameter_tag - if value: - self.value = Parameter(type_, value, max_size, min_size) - self.length = len(self.value) - else: - self.value = None - self.length = 0 - - def __len__(self): - if self.value: - return 4 + self.length - else: - return 0 - - def __call__(self, value = None): - if value == None: - return '%s%s%s' % (self.parameter_tag, hex(len(self.value)).replace('0x', '').zfill(4), self.value()) - else: - self.value(value) - self.length = len(self.value) - #To be used as properties to build the top objects #I know looks bizarre... but will avoid a lot code to be done #I know: @@ -91,59 +80,98 @@ def __call__(self, value = None): #Explicit is better than implicit. #Simple is better than complex. #Complex is better than complicated. -set_system_id = functools.partial(set_string_parameter, 32, 0, '_system_id') -set_password = functools.partial(set_string_parameter, 18, 0, '_password') -set_system_type = functools.partial(set_string_parameter, 26, 0, '_system_type') -set_interface_version = functools.partial(set_int_parameter, 2, '_interface_version') -set_addr_ton = functools.partial(set_int_parameter, 2, '_addr_ton') -set_addr_npi = functools.partial(set_int_parameter, 2, '_addr_npi') -set_address_range = functools.partial(set_string_parameter, 82, 0, '_address_range') -set_service_type = functools.partial(set_string_parameter, 12, 0, '_service_type') -set_source_addr_ton = functools.partial(set_int_parameter, 2, '_source_addr_ton') -set_source_addr_npi = functools.partial(set_int_parameter, 2, '_source_addr_npi') -set_source_addr = functools.partial(set_string_parameter, 42, 0, '_source_addr') -set_dest_addr_ton = functools.partial(set_int_parameter, 2, '_dest_addr_ton') -set_dest_addr_npi = functools.partial(set_int_parameter, 2, '_dest_addr_npi') -set_dest_addr = functools.partial(set_string_parameter, 42, 0, '_dest_add') -set_esm_class = functools.partial(set_int_parameter, 2, '_esm_class') -set_protocol_id = functools.partial(set_int_parameter, 2, '_protocol_id') -set_priority_flag = functools.partial(set_int_parameter, 2, '_priority_flag') -set_schedule_delivery_time = functools.partial(set_string_parameter, 34, 2, '_schedule_delivery_time') -set_validity_period = functools.partial(set_string_parameter, 34, 2, '_validity_period') -set_registered_delivery = functools.partial(set_int_parameter, 2, '_registered_delivery') -set_replace_if_present_flag = functools.partial(set_int_parameter, 2, '_replace_if_present_flag') -set_data_coding = functools.partial(set_int_parameter, 2, '_data_coding') -set_sm_default_msg_id = functools.partial(set_int_parameter, 2, '_sm_default_msg_id') -set_sm_length = functools.partial(set_int_parameter, 2, '_sm_length') -set_short_message = functools.partial(set_string_parameter, 508, 0, '_short_message') - -get_system_id = functools.partial(get_string_parameter, '_system_id') -get_password = functools.partial(get_string_parameter, '_password') -get_system_type = functools.partial(get_string_parameter,'_system_type') + +#SMPP Header +set_command_length = functools.partial(set_int_parameter, 8, 0, 'command_length') +set_command_id = functools.partial(set_int_parameter, 8, 0, '_command_id') +set_command_status = functools.partial(set_int_parameter, 8, 0, '_command_status') +set_sequence_number = functools.partial(set_int_parameter, 8, 0, 'sequence_number') + +#SMPP mandatory parameters +set_system_id = functools.partial(set_string_parameter, 32, 0, '', 'c-octet_string', '_system_id') +set_password = functools.partial(set_string_parameter, 18, 0, '', 'c-octet_string','_password') +set_system_type = functools.partial(set_string_parameter, 26, 0, '', 'c-octet_string', '_system_type') +set_interface_version = functools.partial(set_int_parameter, 2, 52, '_interface_version') +set_addr_ton = functools.partial(set_int_parameter, 2, 0, '_addr_ton') +set_addr_npi = functools.partial(set_int_parameter, 2, 0, '_addr_npi') +set_address_range = functools.partial(set_string_parameter, 82, 0, '', 'c-octet_string', '_address_range') +set_service_type = functools.partial(set_string_parameter, 12, 0, '', 'c-octet_string', '_service_type') +set_source_addr_ton = functools.partial(set_int_parameter, 2, 0, '_source_addr_ton') +set_source_addr_npi = functools.partial(set_int_parameter, 2, 0, '_source_addr_npi') +set_source_addr = functools.partial(set_string_parameter, 42, 0, '', 'c-octet_string', '_source_addr') +set_dest_addr_ton = functools.partial(set_int_parameter, 2, 0, '_dest_addr_ton') +set_dest_addr_npi = functools.partial(set_int_parameter, 2, 0, '_dest_addr_npi') +set_dest_addr = functools.partial(set_string_parameter, 42, 0, '', 'c-octet_string', '_dest_add') +set_esm_class = functools.partial(set_int_parameter, 2, 0, '_esm_class') +set_protocol_id = functools.partial(set_int_parameter, 2, 0, '_protocol_id') +set_priority_flag = functools.partial(set_int_parameter, 2, 0, '_priority_flag') +set_schedule_delivery_time = functools.partial(set_string_parameter, 34, 2, '', 'c-octet_string', '_schedule_delivery_time') +set_validity_period = functools.partial(set_string_parameter, 34, 2, '', 'c-octet_string', '_validity_period') +set_registered_delivery = functools.partial(set_int_parameter, 2, 0, '_registered_delivery') +set_replace_if_present_flag = functools.partial(set_int_parameter, 2, 0, '_replace_if_present_flag') +set_data_coding = functools.partial(set_int_parameter, 2, 0, '_data_coding') +set_sm_default_msg_id = functools.partial(set_int_parameter, 2, 0, '_sm_default_msg_id') +set_sm_length = functools.partial(set_int_parameter, 2, 0, '_sm_length') +set_short_message = functools.partial(set_string_parameter, 508, 0, '', 'octet_string', '_short_message') + +#SMPP Header +get_command_length = functools.partial(get_int_parameter, 'command_length') +get_command_id = functools.partial(get_int_parameter, '_command_id') +get_command_status = functools.partial(get_int_parameter, '_command_status') +get_sequence_number = functools.partial(get_int_parameter, 'sequence_number') + +#SMPP mandatory parameters +get_system_id = functools.partial(get_string_parameter, 'c-octet_string', '_system_id') +get_password = functools.partial(get_string_parameter, 'c-octet_string', '_password') +get_system_type = functools.partial(get_string_parameter,'c-octet_string', '_system_type') get_interface_version = functools.partial(get_int_parameter,'_interface_version') get_addr_ton = functools.partial(get_int_parameter, '_addr_ton') get_addr_npi = functools.partial(get_int_parameter, '_addr_npi') -get_address_range = functools.partial(get_string_parameter, '_address_range') -get_service_type = functools.partial(get_string_parameter, '_service_type') +get_address_range = functools.partial(get_string_parameter, 'c-octet_string', '_address_range') +get_service_type = functools.partial(get_string_parameter, 'c-octet_string', '_service_type') get_source_addr_ton = functools.partial(get_int_parameter, '_source_addr_ton') get_source_addr_npi = functools.partial(get_int_parameter, '_source_addr_npi') -get_source_addr = functools.partial(get_string_parameter, '_source_addr') +get_source_addr = functools.partial(get_string_parameter, 'c-octet_string', '_source_addr') get_dest_addr_ton = functools.partial(get_int_parameter, '_dest_addr_ton') get_dest_addr_npi = functools.partial(get_int_parameter, '_dest_addr_npi') -get_dest_addr = functools.partial(get_string_parameter, '_dest_add') +get_dest_addr = functools.partial(get_string_parameter, 'c-octet_string', '_dest_add') get_esm_class = functools.partial(get_int_parameter, '_esm_class') get_protocol_id = functools.partial(get_int_parameter, '_protocol_id') get_priority_flag = functools.partial(get_int_parameter, '_priority_flag') -get_schedule_delivery_time = functools.partial(get_string_parameter, '_schedule_delivery_time') -get_validity_period = functools.partial(get_string_parameter, '_validity_period') +get_schedule_delivery_time = functools.partial(get_string_parameter, 'c-octet_string', '_schedule_delivery_time') +get_validity_period = functools.partial(get_string_parameter, 'c-octet_string', '_validity_period') get_registered_delivery = functools.partial(get_int_parameter, '_registered_delivery') get_replace_if_present_flag = functools.partial(get_int_parameter, '_replace_if_present_flag') get_data_coding = functools.partial(get_int_parameter, '_data_coding') get_sm_default_msg_id = functools.partial(get_int_parameter, '_sm_default_msg_id') get_sm_length = functools.partial(get_int_parameter, '_sm_length') -get_short_message = functools.partial(get_string_parameter, '_short_message') +get_short_message = functools.partial(get_string_parameter, 'octet_string', '_short_message') + +class TLV(object): + def __init__(self, parameter_tag, type_, value, max_size, min_size = 0): + + self.parameter_tag = parameter_tag + if value: + self.value = Parameter(type_, value, max_size, min_size) + self.length = len(self.value) + else: + self.value = None + self.length = 0 + + def __len__(self): + if self.value: + return 4 + self.length + else: + return 0 + + def __call__(self, value = None): + if value == None: + return '%s%s%s' % (self.parameter_tag, hex(len(self.value)).replace('0x', '').zfill(4), self.value()) + else: + self.value(value) + self.length = len(self.value) class DestAddrSubunit(TLV): def __init__(self, value): @@ -151,7 +179,7 @@ def __init__(self, value): class SourceAddrSubunit(TLV): def __init__(self, value): - TLV.__init__(self, smpp_const.SOURCE_ADDR_SUBUNIT, 'int', value, 2) + TLV.__init__(self, smpp_const.SOURCE_ADDR_SUBUNIT, 'int', value, 2) class DestNetworkType(TLV): def __init__(self, value): From 540b6626c2e174000ac199b6ff0fa4a0be722c6b Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Sun, 8 Apr 2012 18:11:08 -0300 Subject: [PATCH 4/7] Starting the smpp parser. A function will act as a factory to setup smpp commands --- src/{smpp_operation.py => smpp_commands.py} | 0 src/smpp_parser.py | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+) rename src/{smpp_operation.py => smpp_commands.py} (100%) create mode 100644 src/smpp_parser.py diff --git a/src/smpp_operation.py b/src/smpp_commands.py similarity index 100% rename from src/smpp_operation.py rename to src/smpp_commands.py diff --git a/src/smpp_parser.py b/src/smpp_parser.py new file mode 100644 index 0000000..fd4a06f --- /dev/null +++ b/src/smpp_parser.py @@ -0,0 +1,19 @@ +def parser_int_parameter(max_size, data): + return data[:max_size], data[max_size:] + +def parser_c_octet_string(data): + index = data.find('00') + return data[:index], data[index+2:] + +def parser_octet_string(length, data): + return data[:length], data[length:] + +def parse_header(data): + return + +def smpp_parser(data): + (command_length, command_id, + command_status, sequence_number, + data) = data[:8], data[8:16], data[16:24], data[24:32], data[32:] + + From ad5382176fbc34e462b2ac324849a3269adda2e9 Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Mon, 9 Apr 2012 23:19:36 -0300 Subject: [PATCH 5/7] All the mandatory parameters done. --- src/smpp_const.py | 2 -- src/smpp_parts.py | 50 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/smpp_const.py b/src/smpp_const.py index aa036a0..1acd3f2 100644 --- a/src/smpp_const.py +++ b/src/smpp_const.py @@ -152,8 +152,6 @@ '00000103', '80000103') - - command_status = ( '00000000', '00000001', '00000002', diff --git a/src/smpp_parts.py b/src/smpp_parts.py index 0098803..97c5f6b 100644 --- a/src/smpp_parts.py +++ b/src/smpp_parts.py @@ -19,10 +19,10 @@ def set_string_parameter(max_size, min_size, default_value, type_, name, self, v value = value.encode('hex') - if len(value) > max_size: + if len(value) > max_size - 2: raise ValueError('Cannot exceed %s characters' % (max_size/2)) - elif len(value) < min_size: + elif len(value) < min_size - 2: raise ValueError('Cannot be less than %s characters' % (min_size/2)) elif not smpp_values_validation(name, value): @@ -34,7 +34,7 @@ def set_string_parameter(max_size, min_size, default_value, type_, name, self, v elif type_ == 'octet_string': setattr(self, name, value) -def get_string_parameter(name, type_, self): +def get_string_parameter(type_, name, self): value = '' if type_ == 'c-octet_string': @@ -46,10 +46,15 @@ def get_string_parameter(name, type_, self): return value def set_int_parameter(max_size, default_value, name, self, value): + if value is None: value = default_value - value = hex(value).replace('0x', '').zfill(max_size) + if type(value) is str: + value = value.zfill(max_size) + + else: + value = hex(value).replace('0x', '').zfill(max_size) if len(value) > max_size: raise ValueError('Cannot exceed %s: %s' % (max_size, value)) @@ -59,8 +64,9 @@ def set_int_parameter(max_size, default_value, name, self, value): setattr(self, name, value) + def get_int_parameter(name, self): - return int(getattr(self, name), 16) + return int(getattr(self, name),16) def set_bit_parameter(max_size, name, self, value): value = value.zfill(2) @@ -72,6 +78,24 @@ def set_bit_parameter(max_size, name, self, value): def get_bit_parameter(name, self): return getattr(self, name) +def set_command_length(self, value): + length = 0 + for i in self._parameters[1:]: + length += len(getattr(self, i)) + + for i in self._optional_parameters: + length += len(getattr(self, i)) + + self._command_length = hex((length+8)/2).replace('0x','').zfill(8) + +def get_command_length(self): + return int(self._command_length, 16) + +def set_sm_length(self, value): + self._sm_length = hex(len(self._short_message)/2).replace('0x','').zfill(2) + +def get_sm_length(self): + return int(hex(len(self._short_message)/2).replace('0x','').zfill(2), 16) #To be used as properties to build the top objects #I know looks bizarre... but will avoid a lot code to be done @@ -82,10 +106,10 @@ def get_bit_parameter(name, self): #Complex is better than complicated. #SMPP Header -set_command_length = functools.partial(set_int_parameter, 8, 0, 'command_length') +#set_command_length = functools.partial(set_int_parameter, 8, 0, '_command_length') set_command_id = functools.partial(set_int_parameter, 8, 0, '_command_id') set_command_status = functools.partial(set_int_parameter, 8, 0, '_command_status') -set_sequence_number = functools.partial(set_int_parameter, 8, 0, 'sequence_number') +set_sequence_number = functools.partial(set_int_parameter, 8, 0, '_sequence_number') #SMPP mandatory parameters set_system_id = functools.partial(set_string_parameter, 32, 0, '', 'c-octet_string', '_system_id') @@ -101,7 +125,7 @@ def get_bit_parameter(name, self): set_source_addr = functools.partial(set_string_parameter, 42, 0, '', 'c-octet_string', '_source_addr') set_dest_addr_ton = functools.partial(set_int_parameter, 2, 0, '_dest_addr_ton') set_dest_addr_npi = functools.partial(set_int_parameter, 2, 0, '_dest_addr_npi') -set_dest_addr = functools.partial(set_string_parameter, 42, 0, '', 'c-octet_string', '_dest_add') +set_dest_addr = functools.partial(set_string_parameter, 42, 0, '', 'c-octet_string', '_dest_addr') set_esm_class = functools.partial(set_int_parameter, 2, 0, '_esm_class') set_protocol_id = functools.partial(set_int_parameter, 2, 0, '_protocol_id') set_priority_flag = functools.partial(set_int_parameter, 2, 0, '_priority_flag') @@ -111,14 +135,14 @@ def get_bit_parameter(name, self): set_replace_if_present_flag = functools.partial(set_int_parameter, 2, 0, '_replace_if_present_flag') set_data_coding = functools.partial(set_int_parameter, 2, 0, '_data_coding') set_sm_default_msg_id = functools.partial(set_int_parameter, 2, 0, '_sm_default_msg_id') -set_sm_length = functools.partial(set_int_parameter, 2, 0, '_sm_length') +#set_sm_length = functools.partial(set_int_parameter, 2, 0, '_sm_length') set_short_message = functools.partial(set_string_parameter, 508, 0, '', 'octet_string', '_short_message') #SMPP Header -get_command_length = functools.partial(get_int_parameter, 'command_length') +#get_command_length = functools.partial(get_int_parameter, '_command_length') get_command_id = functools.partial(get_int_parameter, '_command_id') get_command_status = functools.partial(get_int_parameter, '_command_status') -get_sequence_number = functools.partial(get_int_parameter, 'sequence_number') +get_sequence_number = functools.partial(get_int_parameter, '_sequence_number') #SMPP mandatory parameters get_system_id = functools.partial(get_string_parameter, 'c-octet_string', '_system_id') @@ -134,7 +158,7 @@ def get_bit_parameter(name, self): get_source_addr = functools.partial(get_string_parameter, 'c-octet_string', '_source_addr') get_dest_addr_ton = functools.partial(get_int_parameter, '_dest_addr_ton') get_dest_addr_npi = functools.partial(get_int_parameter, '_dest_addr_npi') -get_dest_addr = functools.partial(get_string_parameter, 'c-octet_string', '_dest_add') +get_dest_addr = functools.partial(get_string_parameter, 'c-octet_string', '_dest_addr') get_esm_class = functools.partial(get_int_parameter, '_esm_class') get_protocol_id = functools.partial(get_int_parameter, '_protocol_id') get_priority_flag = functools.partial(get_int_parameter, '_priority_flag') @@ -144,7 +168,7 @@ def get_bit_parameter(name, self): get_replace_if_present_flag = functools.partial(get_int_parameter, '_replace_if_present_flag') get_data_coding = functools.partial(get_int_parameter, '_data_coding') get_sm_default_msg_id = functools.partial(get_int_parameter, '_sm_default_msg_id') -get_sm_length = functools.partial(get_int_parameter, '_sm_length') +#get_sm_length = functools.partial(get_int_parameter, '_sm_length') get_short_message = functools.partial(get_string_parameter, 'octet_string', '_short_message') From 06bb26624d1a654016ca3573f50367c38f1bc003 Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Tue, 10 Apr 2012 10:25:52 -0300 Subject: [PATCH 6/7] Finished the length values functions. --- src/smpp_commands.py | 115 +++++++++++++++++-------------------------- src/smpp_const.py | 50 ++++++++++++++++++- src/smpp_parts.py | 66 ++++++++++++++++++++----- 3 files changed, 147 insertions(+), 84 deletions(-) diff --git a/src/smpp_commands.py b/src/smpp_commands.py index 5246644..ef8c0a1 100644 --- a/src/smpp_commands.py +++ b/src/smpp_commands.py @@ -218,24 +218,50 @@ def __init__(self, command_stat, sequence_numb): command_status = command_stat, sequence_number = sequence_numb) -class SubmitSM(Header): - def __init__(self, sequence_numb, - dest_addr_ton, dest_addr_npi, - destination_addr, esm_class, - protocol_id, priority_flag, - registered_delivery, replace_if_present_flag, - data_coding, sm_length, short_message, - - service_type = smpp_const.ESME_ROK, - source_addr_ton = 0, source_addr_npi = 0, - source_addr = '', schedule_delivery_time = '', - validity_period = '', sm_default_msg_id = 0, - - ): - Header.__init__(self, command_id = smpp_const.SUBMIT_SM, - command_status = smpp_const.ESME_ROK, - sequence_number = sequence_numb) - self.service_type = part.ServiceType(service_type) +class SubmitSM(object): + _parameters = ['_command_length', '_command_id', '_command_status', + '_sequence_number', '_service_type', '_source_addr_ton', + '_source_addr_npi', '_source_addr', '_dest_addr_ton', + '_dest_addr_npi', '_dest_addr', '_esm_class', + '_protocol_id', '_priority_flag', '_schedule_delivery_time', + '_validity_period', '_registered_delivery', + '_replace_if_present_flag', '_data_coding', + '_sm_default_msg_id', '_sm_length', '_short_message'] + + _optional_parameters = [] + + __slots__ = _parameters + _optional_parameters + + def __init__(self, **kargs): + for i in self._parameters[4:]: + setattr(self, i[1:], kargs.get(i[1:])) + self.command_id = smpp_const.SUBMIT_SM + self.command_status = smpp_const.ESME_ROK + self.sequence_number = kargs.get('sequence_number') + self.command_length = 0 + + command_length = property(part.get_command_length, part.set_command_length) + command_id = property(part.get_command_id, part.set_command_id) + command_status = property(part.get_command_status, part.set_command_status) + sequence_number = property(part.get_sequence_number, part.set_sequence_number) + service_type = property(part.get_service_type, part.set_service_type) + source_addr_ton = property(part.get_source_addr_ton, part.set_source_addr_ton) + source_addr_npi = property(part.get_source_addr_npi, part.set_source_addr_npi) + source_addr = property(part.get_source_addr, part.set_source_addr) + dest_addr_ton = property(part.get_dest_addr_ton, part.set_dest_addr_ton) + dest_addr_npi = property(part.get_dest_addr_npi, part.set_dest_addr_npi) + dest_addr = property(part.get_dest_addr, part.set_dest_addr) + esm_class = property(part.get_esm_class, part.set_esm_class) + protocol_id = property(part.get_protocol_id, part.set_protocol_id) + priority_flag = property(part.get_priority_flag, part.set_priority_flag) + schedule_delivery_time = property(part.get_schedule_delivery_time, part.set_schedule_delivery_time) + validity_period = property(part.get_validity_period, part.set_validity_period) + registered_delivery = property(part.get_registered_delivery, part.set_registered_delivery) + replace_if_present_flag = property(part.get_replace_if_present_flag, part.set_replace_if_present_flag) + data_coding = property(part.get_data_coding, part.set_data_coding) + sm_default_msg_id = property(part.get_sm_default_msg_id, part.set_sm_default_msg_id) + sm_length = property(part.get_sm_length, part.set_sm_length) + short_message = property(part.get_short_message, part.set_short_message) class EnquireLink(Header): @@ -251,56 +277,3 @@ def __init__(self, sequence_numb): command_status = smpp_const.ESME_ROK, sequence_number = sequence_numb) - -class Client(asyncore.dispatcher): - def __init__(self, host, port, bind): - asyncore.dispatcher.__init__(self) - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.connect( (host, port) ) - self.bind = bind - self.send_buf = '' - self.recv_buf = '' - self.sequence_number = 0 - self.enquire_time = 0 - - def handle_connect(self): - self.bind.sequence_number(self.sequence_number) - self.send(binascii.a2b_hex(self.bind.format_message())) - self.sequence_number += 1 - self.enquire_time = time.time() - - def handle_close(self): - self.close() - - def handle_read(self): - data = self.recv(4) - length = int(binascii.b2a_hex(data),16) - raw_pdu = self.recv(length - 4) - a = data + raw_pdu - print binascii.b2a_hex(a) - - def handle_write(self): - if time.time() - self.enquire_time >= 10: - self.send(binascii.unhexlify(EnquireLink(self.sequence_number).format_message())) - self.sequence_number +=1 - self.enquire_time = time.time() - - - -if __name__ == '__main__': - - bind = BindTransmitter(10, system_id = 'denis', password = 'buga', addr_npi = 1, addr_ton = 2) - #print BindTransmitterResp(10).format_message() - #print BindReceiver(10, system_id = 'denis', password = 'buga', addr_npi = 1, addr_ton = 2).format_message() - #print BindReceiverResp(10, sc_interface_version = 52).format_message() - #print BindTranceiver(10, system_id = 'denis', password = 'buga', addr_npi = 1, addr_ton = 2).format_message() - #print BindTranceiverResp(10, command_stat = smpp_const.ESME_RBINDFAIL, sc_interface_version = 52).format_message() - #print OutBind(10, password = 'buga').format_message() - #print UnBind(10).format_message() - #print UnBindResp(10).format_message() - #print GenericNack(smpp_const.ESME_RALYBND, 10).format_message() - - client = Client('localhost', 8003, bind) - - - asyncore.loop() diff --git a/src/smpp_const.py b/src/smpp_const.py index 1acd3f2..f12b0b8 100644 --- a/src/smpp_const.py +++ b/src/smpp_const.py @@ -123,7 +123,7 @@ ITS_REPLY_TYPE = '1380' ITS_SESSION_INFO = '1383' -command_id = ( +_command_id = ( '80000000', '00000001', '80000001', @@ -152,7 +152,7 @@ '00000103', '80000103') -command_status = ( '00000000', +_command_status = ( '00000000', '00000001', '00000002', '00000003', @@ -200,3 +200,49 @@ '000000c4', '000000fe', '000000ff') + +_optional_parameters = ('0005' +'0006' +'0007' +'0008' +'000d' +'000e' +'000f' +'0010' +'0017' +'0019' +'001d' +'001e' +'0030' +'0201' +'0202' +'0203' +'0204' +'0205' +'020a' +'020b' +'020c' +'020d' +'020e' +'020f' +'0210' +'0302' +'0303' +'0304' +'0381' +'0420' +'0421' +'0422' +'0423' +'0424' +'0425' +'0426' +'0427' +'0501' +'1201' +'1203' +'1204' +'130c' +'1380' +'1383') + \ No newline at end of file diff --git a/src/smpp_parts.py b/src/smpp_parts.py index 97c5f6b..b6afeaa 100644 --- a/src/smpp_parts.py +++ b/src/smpp_parts.py @@ -3,7 +3,7 @@ def smpp_values_validation(name, value): try: - if value in getattr(const, name[1:]): + if value in getattr(const, name): return True else: @@ -34,6 +34,14 @@ def set_string_parameter(max_size, min_size, default_value, type_, name, self, v elif type_ == 'octet_string': setattr(self, name, value) + if name == '_short_message': + #this will update the short message size, for every change in the + #short message; any value is ignored + self.sm_length = 0 #hex(len(self._short_message)/2).replace('0x','').zfill(2) + + self.command_length = 0 + + def get_string_parameter(type_, name, self): value = '' @@ -50,11 +58,7 @@ def set_int_parameter(max_size, default_value, name, self, value): if value is None: value = default_value - if type(value) is str: - value = value.zfill(max_size) - - else: - value = hex(value).replace('0x', '').zfill(max_size) + value = hex(int(value)).replace('0x', '').zfill(max_size) if len(value) > max_size: raise ValueError('Cannot exceed %s: %s' % (max_size, value)) @@ -66,7 +70,7 @@ def set_int_parameter(max_size, default_value, name, self, value): def get_int_parameter(name, self): - return int(getattr(self, name),16) + return int(getattr(self, name), 16) def set_bit_parameter(max_size, name, self, value): value = value.zfill(2) @@ -78,13 +82,23 @@ def set_bit_parameter(max_size, name, self, value): def get_bit_parameter(name, self): return getattr(self, name) + +#Special parameters def set_command_length(self, value): length = 0 for i in self._parameters[1:]: - length += len(getattr(self, i)) + if hasattr(self, i): + length += len(getattr(self, i)) + + else: + break for i in self._optional_parameters: - length += len(getattr(self, i)) + if hasattr(self, i): + length += len(getattr(self, i)) + + else: + length += 0 self._command_length = hex((length+8)/2).replace('0x','').zfill(8) @@ -92,11 +106,17 @@ def get_command_length(self): return int(self._command_length, 16) def set_sm_length(self, value): - self._sm_length = hex(len(self._short_message)/2).replace('0x','').zfill(2) + try: + self._sm_length = hex(len(self._short_message)/2).replace('0x','').zfill(2) + + except AttributeError: + self._sm_length = value def get_sm_length(self): return int(hex(len(self._short_message)/2).replace('0x','').zfill(2), 16) +#End of special parameters + #To be used as properties to build the top objects #I know looks bizarre... but will avoid a lot code to be done #I know: @@ -172,6 +192,30 @@ def get_sm_length(self): get_short_message = functools.partial(get_string_parameter, 'octet_string', '_short_message') +#(name, length, value) + +def set_tlv_length(tag, self, value): + setattr(self, name, hex(len(getattr(self, tag))/2).replace('0x','').zfill(2)) + +def get_tlv_length(tag, self): + return int(hex(len(getattr(self, tag))/2).replace('0x','').zfill(2), 16) + +set_tag_name = functools.partial(set_int_parameter, 2, 0, '_tag_name') +get_tag_name = functools.partial(get_int_parameter, '_tag_name') + + +class TLV(object): + def __init__(self, name): + self.name = name + + name = property(get_tag_name, set_tag_name) + + def __len__(self): + return self.length + 4 + + def format_message(self): + return '%s%s%s' % (self.name, self.length, self.value) + class TLV(object): def __init__(self, parameter_tag, type_, value, max_size, min_size = 0): @@ -196,7 +240,7 @@ def __call__(self, value = None): else: self.value(value) self.length = len(self.value) - + class DestAddrSubunit(TLV): def __init__(self, value): TLV.__init__(self, smpp_const.DEST_ADDR_SUBUNIT, 'int', value, 2) From ef4d6eede2857b445bb0ae5c176c64b2f477d9e6 Mon Sep 17 00:00:00 2001 From: Denis Doria Date: Tue, 10 Apr 2012 10:26:35 -0300 Subject: [PATCH 7/7] Added code example. --- src/ex.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/ex.py diff --git a/src/ex.py b/src/ex.py new file mode 100644 index 0000000..291b1a0 --- /dev/null +++ b/src/ex.py @@ -0,0 +1,38 @@ +import smpp_const +import smpp_parts as part +import asyncore +import socket +import binascii +import time +import datetime +from smpp_commands import SubmitSM + +submit_sm = SubmitSM(command_length='60', command_id=4, command_status=0, + sequence_number=5, service_type='', source_addr_ton=2, + source_addr_npi=8, source_addr='555', dest_addr_ton='1', + dest_addr_npi=1, dest_addr='555555555', esm_class=0, + protocol_id=0, priority_flag=0, schedule_delivery_time='', + validity_period='', registered_delivery=0, replace_if_present_flag=0, + data_coding=0, sm_default_msg_id=0, sm_length=14, + short_message='Hello wikipediasdsda') + +print 'Showing all the parameters: (name, external value, internal value)' +for i in submit_sm.__slots__: + print i, '('+str(getattr(submit_sm, i[1:]))+')', '('+str(getattr(submit_sm, i))+')' + +print '\nShort message update will cause an update in the sm_length automagically' +print "submit_sm.short_message = 'aaaaa'" +submit_sm.short_message = 'aaaaa' + +for i in submit_sm.__slots__: + print i, '('+str(getattr(submit_sm, i[1:]))+')', '('+str(getattr(submit_sm, i))+')' + +print '\nForce hex data, and force short_message and command_length update' +print "submit_sm._short_message = 'aaaaaaaa'; submit_sm.sm_length = 0; submit_sm.command_length = 0" + +submit_sm._short_message = 'aaaaaaaa' +submit_sm.sm_length = 0 +submit_sm.command_length = 0 + +for i in submit_sm.__slots__: + print i, '('+str(getattr(submit_sm, i[1:]))+')', '('+str(getattr(submit_sm, i))+')'