pdu_sms 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ module PduSms
2
+ class MessageReference
3
+
4
+ def initialize(num)
5
+ if (0..255).include?(num)
6
+ @mr = num
7
+ else
8
+ raise ArgumentError, 'The "num" is incorrect'
9
+ end
10
+ end
11
+
12
+ def MessageReference.encode_ms(num)
13
+ new(num).freeze
14
+ end
15
+
16
+ def MessageReference.decode_ms(pdu)
17
+ new(MessageReference.cut_off_pdu(pdu, :current, :ms).to_i(2)).freeze
18
+ end
19
+
20
+ def MessageReference.cut_off_pdu(pdu, part=:all, type=:ms) # tail current
21
+ part_pdu = PDUType.cut_off_pdu(pdu, :tail)
22
+ raise ArgumentError, 'The "pdu" is incorrect' if part_pdu.length < 2
23
+ current = part_pdu[0..1]
24
+ tail = part_pdu[2..-1]
25
+ case part
26
+ when :current then current
27
+ when :tail then tail
28
+ else [current,tail]
29
+ end
30
+ end
31
+
32
+ def get_hex
33
+ '%02x' % @mr
34
+ end
35
+
36
+ def get_mr
37
+ @mr
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,57 @@
1
+ module PduSms
2
+ class OriginatingAddress < Phone
3
+
4
+ def initialize(type=false, data=false, number_play_identifier=false, type_number=false)
5
+ if type == :decode_sc
6
+ _set_pdu_hex OriginatingAddress.cut_off_pdu(data, :current, :sc)
7
+ elsif type == :encode_sc
8
+ _set_phone_number data, number_play_identifier, type_number
9
+ end
10
+ end
11
+
12
+ def OriginatingAddress.encode_sc(phone, number_play_identifier=false, type_number=false)
13
+ new(:encode_sc, phone, number_play_identifier, type_number)
14
+ end
15
+
16
+ def OriginatingAddress.decode_sc(pdu)
17
+ new(:decode_sc, pdu).freeze
18
+ end
19
+
20
+ def OriginatingAddress.cut_off_pdu(pdu, part=:all, type=:sc) # tail current
21
+ part_pdu = PDUType.cut_off_pdu(pdu, :tail)
22
+ raise ArgumentError, 'The "pdu" is incorrect' if part_pdu.length < 4
23
+ length = part_pdu[0..1].to_i(16)
24
+ if length % 2 == 0
25
+ current = part_pdu[0..length+3]
26
+ tail = part_pdu[length+4..-1]
27
+ else
28
+ current = part_pdu[0..length+4]
29
+ tail = part_pdu[length+5..-1]
30
+ end
31
+ case part
32
+ when :current then current
33
+ when :tail then tail
34
+ else [current,tail]
35
+ end
36
+ end
37
+
38
+ def get_hex
39
+ '%s%s' % [_address_length, _get_hex_type_and_phone]
40
+ end
41
+
42
+ private
43
+
44
+ def _set_pdu_hex(str_pdu)
45
+ _set_hex_type_and_phone(str_pdu[2..-1])
46
+ self
47
+ end
48
+
49
+ def _address_length
50
+ if @number_plan_identifier == ID_ALPHANUMERIC
51
+ '%02x' % (@phone_number.length * 0.875 * 2).round
52
+ else
53
+ '%02x' % @phone_number.length
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,126 @@
1
+
2
+ module PduSms
3
+
4
+ class PacketDataUnit
5
+
6
+ attr_reader(:sca,:service_center_address,:pdu_type,:mr,:message_reference,:da,:destination_address,
7
+ :pid,:protocol_identifier,:dcs,:data_coding_scheme,:vp,:validity_period,:udl,:user_data_length,:ud,:user_data,
8
+ :oa,:originating_address,:scts,:service_center_time_stamp)
9
+
10
+ def initialize(sca: false, pdu_type: false, mr: false, da: false, pid: false, dcs: false, vp: false, udl: false, ud: false, oa: false, scts: false)
11
+ raise ArgumentError, 'sca parameter should contain an object of class ServiceCenterAddress' unless ServiceCenterAddress == sca.class
12
+ raise ArgumentError, 'pdu_type parameter should contain an object of class PDUType' unless PDUType == pdu_type.class
13
+ raise ArgumentError, 'mr parameter should contain an object of class MessageReference' unless mr == false or MessageReference == mr.class
14
+ raise ArgumentError, 'da parameter should contain an object of class DestinationAddress' unless da == false or DestinationAddress == da.class
15
+ raise ArgumentError, 'pid parameter should contain an object of class ProtocolIdentifier' unless ProtocolIdentifier == pid.class
16
+ raise ArgumentError, 'dcs parameter should contain an object of class DataCodingScheme' unless DataCodingScheme == dcs.class
17
+ raise ArgumentError, 'vp parameter should contain an object of class ValidityPeriod' unless vp == false or ValidityPeriod == vp.class
18
+ raise ArgumentError, 'udl parameter should contain an object of class UserDataLength' unless UserDataLength == udl.class
19
+ raise ArgumentError, 'ud parameter should contain an object of class UserData' unless UserData == ud.class
20
+ raise ArgumentError, 'oa parameter should contain an object of class OriginatingAddress' unless oa == false or OriginatingAddress == oa.class
21
+ raise ArgumentError, 'scts parameter should contain an object of class ServiceCenterTimeStamp' unless scts == false or ServiceCenterTimeStamp == scts.class
22
+ @sca = @service_center_address = sca
23
+ @pdu_type = pdu_type
24
+ @mr = @message_reference = mr
25
+ @da = @destination_address = da
26
+ @pid = @protocol_identifier = pid
27
+ @dcs = @data_coding_scheme = dcs
28
+ @vp = @validity_period = vp
29
+ @udl = @user_data_length = udl
30
+ @ud = @user_data = ud
31
+ @oa = @originating_address = oa
32
+ @scts = @service_center_time_stamp = scts
33
+ end
34
+
35
+ def PacketDataUnit.encode_ms(phone, message, coding: :auto, phone_npi: false, phone_ton: false, sca: false, sca_npi: false, sca_ton: false, rp: REPLY_PATH_0, srr: STATUS_REPORT_REQUEST_0, vp: false, rd: REJECT_DUPLICATES_0, message_class: false, compressed: UNCOMPRESSED)
36
+ user_data_array = UserData.encode_ms(message, coding)
37
+ user_data_array.collect.each_with_index do |user_data, current_num_pdu|
38
+ service_center_address = ServiceCenterAddress.encode_ms(sca, sca_npi, sca_ton)
39
+ destination_address = DestinationAddress.encode_ms(phone, phone_npi, phone_ton)
40
+ protocol_identifier = ProtocolIdentifier.encode_ms
41
+ message_reference = MessageReference.encode_ms(current_num_pdu)
42
+ validity_period = ValidityPeriod.encode_ms(vp)
43
+ pdu_type = PDUType.encode_ms(rp:rp, srr:srr, rd:rd, udhi: user_data.get_udh, vpf: validity_period.is_setup)
44
+ data_coding_scheme = DataCodingScheme.encode_ms(compressed: compressed, message_class: message_class, alphabet: user_data.get_coding)
45
+ user_data_length = UserDataLength.encode_ms(user_data)
46
+ new(sca: service_center_address, pdu_type: pdu_type, mr: message_reference, da: destination_address, pid: protocol_identifier, dcs: data_coding_scheme, vp: validity_period, udl: user_data_length, ud: user_data).freeze
47
+ end
48
+ end
49
+
50
+ def PacketDataUnit.decode_ms(pdu)
51
+ service_center_address = ServiceCenterAddress.decode_ms(pdu)
52
+ pdu_type = PDUType.decode_ms(pdu)
53
+ message_reference = MessageReference.decode_ms(pdu)
54
+ destination_address = DestinationAddress.decode_ms(pdu)
55
+ protocol_identifier = ProtocolIdentifier.decode_ms(pdu)
56
+ data_coding_scheme = DataCodingScheme.decode_ms(pdu)
57
+ validity_period = ValidityPeriod.decode_ms(pdu)
58
+ user_data_length = UserDataLength.decode_ms(pdu)
59
+ user_data = UserData.decode_ms(pdu)
60
+ new(sca: service_center_address, pdu_type: pdu_type, mr: message_reference, da: destination_address, pid: protocol_identifier, dcs: data_coding_scheme, vp: validity_period, udl: user_data_length, ud: user_data).freeze
61
+ end
62
+
63
+ def PacketDataUnit.encode_sc(sca, phone, message, coding: :auto, sca_npi: false, sca_ton: false, phone_npi: false, phone_ton: false, rp: REPLY_PATH_0, sri: STATUS_REPORT_INDICATION_0, mms: MORE_MESSAGES_TO_SEND_0, message_class: false, compressed: UNCOMPRESSED, scts: Time.now.getutc.to_i)
64
+ user_data_array = UserData.encode_sc(message, coding)
65
+ user_data_array.collect do |user_data|
66
+ service_center_address = ServiceCenterAddress.encode_sc(sca, sca_npi, sca_ton)
67
+ pdu_type = PDUType.encode_sc(rp: rp, udhi: user_data.get_udh, sri: sri, mms: mms)
68
+ originating_address = OriginatingAddress.encode_sc(phone, phone_npi, phone_ton)
69
+ protocol_identifier = ProtocolIdentifier.encode_sc
70
+ data_coding_scheme = DataCodingScheme.encode_sc(compressed: compressed, message_class: message_class, alphabet: user_data.get_coding)
71
+ service_center_time_stamp = ServiceCenterTimeStamp.encode_sc(scts)
72
+ user_data_length = UserDataLength.encode_sc(user_data)
73
+ new(sca: service_center_address, pdu_type: pdu_type, pid: protocol_identifier, dcs: data_coding_scheme, udl: user_data_length, ud: user_data, oa: originating_address, scts: service_center_time_stamp).freeze
74
+ end
75
+ end
76
+
77
+ def PacketDataUnit.decode_sc(pdu)
78
+ service_center_address = ServiceCenterAddress.decode_sc(pdu)
79
+ pdu_type = PDUType.decode_sc(pdu)
80
+ originating_address = OriginatingAddress.decode_sc(pdu)
81
+ protocol_identifier = ProtocolIdentifier.decode_sc(pdu)
82
+ data_coding_scheme = DataCodingScheme.decode_sc(pdu)
83
+ service_center_time_stamp = ServiceCenterTimeStamp.decode_sc(pdu)
84
+ user_data_length = UserDataLength.decode_sc(pdu)
85
+ user_data = UserData.decode_sc(pdu)
86
+ new(sca: service_center_address, pdu_type: pdu_type, pid: protocol_identifier, dcs: data_coding_scheme, udl: user_data_length, ud: user_data, oa: originating_address, scts: service_center_time_stamp).freeze
87
+ end
88
+
89
+ def PacketDataUnit.decode(pdu)
90
+ pdu_type = PDUType.decode(pdu)
91
+ if pdu_type.message_type_indicator_in?
92
+ decode_sc(pdu)
93
+ elsif pdu_type.message_type_indicator_out?
94
+ decode_ms(pdu)
95
+ else
96
+ raise ArgumentError, 'failed to recognize the type of package'
97
+ end
98
+ end
99
+
100
+ def get_hex
101
+ if @pdu_type.message_type_indicator_out?
102
+ '' << @sca.get_hex << @pdu_type.get_hex << @mr.get_hex << @da.get_hex << @pid.get_hex << @dcs.get_hex << @vp.get_hex << @udl.get_hex << @ud.get_hex
103
+ elsif @pdu_type.message_type_indicator_in?
104
+ '' << @sca.get_hex << @pdu_type.get_hex << @oa.get_hex << @pid.get_hex << @dcs.get_hex << @scts.get_hex << @udl.get_hex << @ud.get_hex
105
+ else
106
+ raise PacketDataUnitError, 'oops SMS-SUBMIT not supported by this version of the library'
107
+ end
108
+ end
109
+
110
+ def get_message
111
+ @ud.get_message
112
+ end
113
+
114
+ def get_phone_number
115
+ if @pdu_type.message_type_indicator_out?
116
+ @da.get_phone_number
117
+ elsif @pdu_type.message_type_indicator_in?
118
+ @oa.get_phone_number
119
+ else
120
+ raise PacketDataUnitError, 'oops SMS-SUBMIT not supported by this version of the library'
121
+ end
122
+ end
123
+
124
+ end
125
+ end
126
+
@@ -0,0 +1,2 @@
1
+ class PacketDataUnitError < StandardError
2
+ end
@@ -0,0 +1,179 @@
1
+ module PduSms
2
+ class PDUType
3
+
4
+ def initialize(type, rp: REPLY_PATH_0, udhi: USER_DATA_HEADER_INCLUDED_0, mti: MESSAGE_TYPE_INDICATOR_01, vpf: false, srr: false, sri: false, rd: false, mms: false)
5
+ raise ArgumentError, 'The "rp" is incorrect' unless (REPLY_PATH_0..REPLY_PATH_1).include?(rp)
6
+ raise ArgumentError, 'The "udhi" is incorrect' unless (USER_DATA_HEADER_INCLUDED_0..USER_DATA_HEADER_INCLUDED_1).include?(udhi)
7
+ raise ArgumentError, 'The "mti" is incorrect' unless (MESSAGE_TYPE_INDICATOR_00..MESSAGE_TYPE_INDICATOR_11).include?(mti)
8
+ if mti == MESSAGE_TYPE_INDICATOR_01
9
+ raise ArgumentError, 'The "srr" is incorrect' unless (STATUS_REPORT_REQUEST_0..STATUS_REPORT_REQUEST_1).include?(srr)
10
+ raise ArgumentError, 'The "vpf" is incorrect' unless (VALIDITY_PERIOD_FORMAT_00..VALIDITY_PERIOD_FORMAT_11).include?(vpf)
11
+ raise ArgumentError, 'The "rd" is incorrect' unless (REJECT_DUPLICATES_0..REJECT_DUPLICATES_1).include?(rd)
12
+ elsif mti == MESSAGE_TYPE_INDICATOR_00
13
+ raise ArgumentError, 'The "sri" is incorrect' unless (STATUS_REPORT_INDICATION_0..STATUS_REPORT_INDICATION_1).include?(sri)
14
+ raise ArgumentError, 'The "mms" is incorrect' unless (MORE_MESSAGES_TO_SEND_0..MORE_MESSAGES_TO_SEND_1).include?(mms)
15
+ end
16
+ @rp = rp
17
+ @udhi = udhi
18
+ @srr = srr
19
+ @vpf = vpf
20
+ @rd = rd
21
+ @mti = mti
22
+ @mms = mms
23
+ @sri = sri
24
+ end
25
+
26
+ def PDUType.encode(rp: REPLY_PATH_0, udhi: USER_DATA_HEADER_INCLUDED_0, srr: STATUS_REPORT_REQUEST_0, vpf: VALIDITY_PERIOD_FORMAT_00, rd: REJECT_DUPLICATES_0, mti: MESSAGE_TYPE_INDICATOR_01, sri: STATUS_REPORT_INDICATION_0, mms:MORE_MESSAGES_TO_SEND_0)
27
+ if mti == MESSAGE_TYPE_INDICATOR_01
28
+ PDUType.encode_ms(rp:rp,udhi:udhi, srr:srr, vpf:vpf, rd:rd)
29
+ elsif mti == MESSAGE_TYPE_INDICATOR_00
30
+ PDUType.encode_sc(rp:rp, udhi:udhi, sri:sri, mms:mms)
31
+ elsif mti == MESSAGE_TYPE_INDICATOR_10
32
+ raise PacketDataUnitError, 'oops SMS-SUBMIT not supported by this version of the library'
33
+ end
34
+ end
35
+
36
+ def PDUType.decode(pdu_str)
37
+ pdu = '%08b' % PDUType.cut_off_pdu(pdu_str, :current, :ms)
38
+ mti = pdu[6..7].to_i(2)
39
+ if mti == MESSAGE_TYPE_INDICATOR_00
40
+ PDUType.decode_sc(pdu_str)
41
+ elsif mti == MESSAGE_TYPE_INDICATOR_01
42
+ PDUType.decode_ms(pdu_str)
43
+ elsif mti == MESSAGE_TYPE_INDICATOR_10
44
+ raise PacketDataUnitError, 'oops SMS-SUBMIT not supported by this version of the library'
45
+ else
46
+ raise PacketDataUnitError, 'format error'
47
+ end
48
+ end
49
+
50
+ def PDUType.encode_ms(rp: REPLY_PATH_0, udhi: USER_DATA_HEADER_INCLUDED_0, srr: STATUS_REPORT_REQUEST_0, vpf: VALIDITY_PERIOD_FORMAT_00, rd: REJECT_DUPLICATES_0)
51
+ new(:encode_ms, rp:rp, udhi:udhi, srr:srr, vpf:vpf, rd:rd, mti:MESSAGE_TYPE_INDICATOR_01).freeze
52
+ end
53
+
54
+ def PDUType.decode_ms(pdu_str)
55
+ pdu = '%08b' % PDUType.cut_off_pdu(pdu_str, :current, :ms).to_i(16)
56
+ raise ArgumentError, 'wrong format "PDU" package' if pdu[6..7].to_i(2) != MESSAGE_TYPE_INDICATOR_01
57
+ new(:decode_ms, rp:pdu[0].to_i(2), udhi:pdu[1].to_i(2), srr:pdu[2].to_i(2), vpf:pdu[3..4].to_i(2), rd:pdu[5].to_i(2), mti:MESSAGE_TYPE_INDICATOR_01).freeze
58
+ end
59
+
60
+ def PDUType.encode_sc(rp: REPLY_PATH_0, udhi: USER_DATA_HEADER_INCLUDED_0, sri: STATUS_REPORT_INDICATION_0, mms:MORE_MESSAGES_TO_SEND_0)
61
+ new(:encode_ms, rp:rp, udhi:udhi, sri:sri, mms:mms, mti:MESSAGE_TYPE_INDICATOR_00).freeze
62
+ end
63
+
64
+ def PDUType.decode_sc(pdu_str)
65
+ pdu = '%08b' % PDUType.cut_off_pdu(pdu_str, :current, :sc).to_i(16)
66
+ raise ArgumentError, 'wrong format "PDU" package' if pdu[6..7].to_i(2) != MESSAGE_TYPE_INDICATOR_00
67
+ new(:decode_ms, rp:pdu[0].to_i(2), udhi:pdu[1].to_i(2), sri:pdu[2].to_i(2), mms:pdu[5].to_i(2), mti:MESSAGE_TYPE_INDICATOR_00).freeze
68
+ end
69
+
70
+ def PDUType.cut_off_pdu(pdu, part=:all, type=:ms) # tail current
71
+ part_pdu = ServiceCenterAddress.cut_off_pdu(pdu, :tail)
72
+ raise TypeError.new('Слишком короткая строка') if part_pdu.length < 2
73
+ current = part_pdu[0..1]
74
+ tail = part_pdu[2..-1]
75
+ case part
76
+ when :current then current
77
+ when :tail then tail
78
+ else [current,tail]
79
+ end
80
+ end
81
+
82
+ def reply_path?
83
+ @rp == REPLY_PATH_1
84
+ end
85
+
86
+ def user_data_header_included?
87
+ @udhi == USER_DATA_HEADER_INCLUDED_1
88
+ end
89
+
90
+ def status_report_request?
91
+ @srr == STATUS_REPORT_REQUEST_1
92
+ end
93
+
94
+ def validity_period_format_off?
95
+ @vpf == VALIDITY_PERIOD_FORMAT_00
96
+ end
97
+
98
+ def validity_period_format_reserve?
99
+ @vpf == VALIDITY_PERIOD_FORMAT_01
100
+ end
101
+
102
+ def validity_period_format_relative?
103
+ @vpf == VALIDITY_PERIOD_FORMAT_10
104
+ end
105
+
106
+ def validity_period_format_absolute?
107
+ @vpf == VALIDITY_PERIOD_FORMAT_11
108
+ end
109
+
110
+ def reject_duplicates?
111
+ @rd == REJECT_DUPLICATES_1
112
+ end
113
+
114
+ def message_type_indicator_in?
115
+ @mti == MESSAGE_TYPE_INDICATOR_00
116
+ end
117
+
118
+ def message_type_indicator_out?
119
+ @mti == MESSAGE_TYPE_INDICATOR_01
120
+ end
121
+
122
+ def message_type_indicator_report?
123
+ @mti == MESSAGE_TYPE_INDICATOR_10
124
+ end
125
+
126
+ def message_type_indicator_reserve?
127
+ @mti == MESSAGE_TYPE_INDICATOR_11
128
+ end
129
+
130
+ def more_messages_to_send?
131
+ @mms == MORE_MESSAGES_TO_SEND_1
132
+ end
133
+
134
+ def status_report_indication?
135
+ @sri == STATUS_REPORT_INDICATION_1
136
+ end
137
+
138
+ def get_reply_path
139
+ '%b' % @rp
140
+ end
141
+
142
+ def get_user_data_header_included
143
+ '%b' % @udhi
144
+ end
145
+
146
+ def get_status_report_request
147
+ '%b' % @srr
148
+ end
149
+
150
+ def get_validity_period_format
151
+ '%02b' % @vpf
152
+ end
153
+
154
+ def get_reject_duplicates
155
+ '%b' % @rd
156
+ end
157
+
158
+ def get_message_type_indicator
159
+ '%02b' % @mti
160
+ end
161
+
162
+ def get_status_report_indication
163
+ '%b' % @sri
164
+ end
165
+
166
+ def get_more_messages_to_send
167
+ '%b' % @mms
168
+ end
169
+
170
+ def get_hex
171
+ if message_type_indicator_out?
172
+ '%02x' % [('' << get_reply_path << get_user_data_header_included << get_status_report_request << get_validity_period_format << get_reject_duplicates << get_message_type_indicator).to_i(2)]
173
+ elsif message_type_indicator_in?
174
+ '%02x' % [('' << get_reply_path << get_user_data_header_included << get_status_report_indication << '00' << get_more_messages_to_send << get_message_type_indicator).to_i(2)]
175
+ end
176
+ end
177
+
178
+ end
179
+ end
@@ -0,0 +1,121 @@
1
+ module PduSms
2
+
3
+ class Phone
4
+
5
+ attr_reader(:number_plan_identifier, :type_number)
6
+
7
+ @phone_number = ''
8
+ @number_plan_identifier = false
9
+ @type_number = false
10
+
11
+ def get_phone_number
12
+ if @number_plan_identifier == ID_INTERNATIONAL
13
+ '+%s' % @phone_number
14
+ else
15
+ '%s' % @phone_number
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def _auto_detect(phone_number)
22
+ if /^\+\d+$/ === phone_number
23
+ @number_plan_identifier = ID_INTERNATIONAL
24
+ @type_number = TP_ISDN
25
+ elsif /^\d+$/ === phone_number
26
+ @number_plan_identifier = ID_UNKNOWN
27
+ @type_number = TP_ISDN
28
+ elsif is_7bit?(phone_number)
29
+ @number_plan_identifier = ID_ALPHANUMERIC
30
+ @type_number = TP_UNKNOWN
31
+ else
32
+ raise PacketDataUnitError, 'Could not automatically determine the type of phone number'
33
+ end
34
+ self
35
+ end
36
+
37
+ def _check_phone?
38
+ if @number_plan_identifier == ID_ALPHANUMERIC
39
+ is_7bit?(@phone_number)
40
+ else
41
+ /^\d+$/ === @phone_number
42
+ end
43
+ end
44
+
45
+ def _get_hex_type_and_phone
46
+ if @number_plan_identifier == ID_ALPHANUMERIC
47
+ '%s%s' % [_type_of_address_hex, encode_7bit(@phone_number)]
48
+ else
49
+ '%s%s' % [_type_of_address_hex, _convert_to_bcd_format]
50
+ end
51
+ end
52
+
53
+ def _set_phone_number(phone_number, number_play_identifier=false, type_number=false)
54
+ if number_play_identifier == false or type_number == false
55
+ _auto_detect(phone_number)
56
+ else
57
+ raise ArgumentError, 'Incorrect type of phone number' unless (TP_UNKNOWN..TP_RESERVED).include?(type_number)
58
+ raise ArgumentError, 'Invalid type id telephone' unless (ID_UNKNOWN..ID_RESERVED).include?(number_play_identifier)
59
+ @type_number = type_number
60
+ @number_plan_identifier = number_play_identifier
61
+ end
62
+
63
+ if @number_plan_identifier == ID_INTERNATIONAL and phone_number[0] == '+'
64
+ @phone_number = phone_number[1..-1]
65
+ else
66
+ @phone_number = phone_number
67
+ end
68
+
69
+ unless _check_phone?
70
+ @phone_number = ''
71
+ raise ArgumentError, 'Phone number is invalid'
72
+ end
73
+ self
74
+ end
75
+
76
+ private
77
+
78
+ def _set_hex_type_and_phone(bcd)
79
+ _convert_to_normal_format bcd
80
+ unless _check_phone?
81
+ @phone_number = ''
82
+ raise ArgumentError, 'Phone number is invalid'
83
+ end
84
+ self
85
+ end
86
+
87
+ def _convert_to_bcd_format
88
+ if @phone_number[0] == ?+
89
+ clear_phone = @phone_number[1..-1]
90
+ else
91
+ clear_phone = @phone_number
92
+ end
93
+ if clear_phone.length % 2 != 0
94
+ clear_phone += 'F'
95
+ end
96
+ encode_bcd(clear_phone)
97
+ end
98
+
99
+ def _convert_to_normal_format(bcd)
100
+ @phone_number = ''
101
+ if bcd.length < 4
102
+ raise ArgumentError, 'Wrong format'
103
+ end
104
+ raise ArgumentError, 'Incorrect number plan identifier' unless (128..255).include?(bcd[0..1].to_i(16))
105
+ number_type = '%08b' % bcd[0..1].to_i(16)
106
+ @number_plan_identifier = number_type[1..3].to_i(2)
107
+ @type_number = number_type[4..7].to_i(2)
108
+ if @number_plan_identifier == ID_ALPHANUMERIC
109
+ @phone_number = decode_7bit(bcd[2..-1])
110
+ else
111
+ @phone_number = decode_bcd(bcd[2..-1])[/[fF]$/] ? decode_bcd(bcd[2..-1])[0..-2] : decode_bcd(bcd[2..-1])
112
+ end
113
+ self
114
+ end
115
+
116
+ def _type_of_address_hex
117
+ '%02x' % ('1%03b%04b' % [@number_plan_identifier, @type_number]).to_i(2)
118
+ end
119
+
120
+ end
121
+ end