Move PDU fields methods into their own classes
parent
dbd2f09ec2
commit
1c3521586a
|
@ -1,19 +1,30 @@
|
|||
require 'biju/pdu/gsm7bit'
|
||||
require 'biju/pdu/ucs2'
|
||||
|
||||
require 'biju/pdu/user_data'
|
||||
require 'biju/pdu/data_coding_scheme'
|
||||
|
||||
require 'biju/pdu/phone_number'
|
||||
require 'biju/pdu/type_of_address'
|
||||
|
||||
module Biju
|
||||
module PDU
|
||||
ENCODING = {
|
||||
gsm7bit: GSM7Bit,
|
||||
ucs2: UCS2,
|
||||
}
|
||||
def self.encode(phone_number, message, type_of_address: :international)
|
||||
phone_number = PhoneNumber.encode(phone_number)
|
||||
user_data = UserData.encode(message)
|
||||
|
||||
def self.encode(hash)
|
||||
end
|
||||
|
||||
def self.encode_user_data(message, encoding = :gsm7bit)
|
||||
raise ArgumentError, "Unknown encoding" unless ENCODING.has_key?(encoding)
|
||||
ENCODING[encoding].encode(message)
|
||||
[
|
||||
'00',
|
||||
'01',
|
||||
'00', # TP-Message-Reference
|
||||
"%02x" % phone_number.length,
|
||||
"%02x" % phone_number.type_of_address.hex,
|
||||
phone_number.number,
|
||||
'00', # TP-PID: Protocol identifier
|
||||
"%02x" % user_data.encoding.hex,
|
||||
"%02x" % user_data.length,
|
||||
user_data.message
|
||||
].join
|
||||
end
|
||||
|
||||
def self.decode(string)
|
||||
|
@ -32,36 +43,14 @@ module Biju
|
|||
'%S%M%H%d%m%y%Z'),
|
||||
user_data_length: string[52..53],
|
||||
}
|
||||
res[:sender_number] = string[22..(22 + res[:address_length])].scan(/../)
|
||||
.map(&:reverse).join.chop
|
||||
res[:user_data] = PDU.decode_user_data(string[54..-1],
|
||||
res[:sender_number] = PhoneNumber.new(
|
||||
string[22, res[:address_length] + (res[:address_length].odd? ? 1 : 0)],
|
||||
type_of_address: res[:address_type])
|
||||
res[:user_data] = UserData.new(message: string[54..-1],
|
||||
encoding: res[:data_coding_scheme],
|
||||
length: res[:user_data_length].hex)
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def self.decode_user_data(message, encoding: '00', length: 0)
|
||||
encoding = data_coding_scheme(encoding) unless encoding.is_a?(Symbol)
|
||||
|
||||
raise ArgumentError, "Unknown encoding" unless ENCODING.has_key?(encoding)
|
||||
ENCODING[encoding].decode(message, length: length)
|
||||
end
|
||||
|
||||
def self.data_coding_scheme(dcs)
|
||||
dcs = dcs.hex if dcs.is_a?(String)
|
||||
if dcs & 0b11000000 == 0
|
||||
case dcs & 0b00001100
|
||||
when 0
|
||||
:gsm7bit
|
||||
when 4
|
||||
:gsm8bit
|
||||
when 8
|
||||
:ucs2
|
||||
when 12
|
||||
:reserved
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
module Biju
|
||||
module PDU
|
||||
class DataCodingScheme
|
||||
DATA_CODING_SCHEME = {
|
||||
gsm7bit: 0,
|
||||
gsm8bit: 4,
|
||||
ucs2: 8,
|
||||
reserved: 12,
|
||||
}
|
||||
|
||||
def self.autodetect(message)
|
||||
message.chars.each do |char|
|
||||
return :ucs2 unless GSM7Bit::BASIC_7BIT_CHARACTER_SET.include?(char) ||
|
||||
GSM7Bit::BASIC_7BIT_CHARACTER_SET_EXTENSION.has_value?(char)
|
||||
end
|
||||
|
||||
:gsm7bit
|
||||
end
|
||||
|
||||
def initialize(dcs, options = {})
|
||||
unless dcs.is_a?(Symbol)
|
||||
dcs = dcs.hex if dcs.is_a?(String)
|
||||
if dcs & 0b11000000 == 0
|
||||
dcs = DATA_CODING_SCHEME.key(dcs & 0b00001100)
|
||||
else
|
||||
raise "Unsupported"
|
||||
end
|
||||
end
|
||||
|
||||
@dcs = dcs
|
||||
end
|
||||
|
||||
def to_sym
|
||||
@dcs
|
||||
end
|
||||
|
||||
def hex
|
||||
DATA_CODING_SCHEME[@dcs]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
module Biju
|
||||
module PDU
|
||||
class PhoneNumber
|
||||
attr_accessor :type_of_address, :number
|
||||
|
||||
def self.encode(number, type_of_address: :international)
|
||||
number << 'F' if number.length.odd?
|
||||
new(
|
||||
number.scan(/../).map(&:reverse).join,
|
||||
type_of_address: type_of_address
|
||||
)
|
||||
end
|
||||
|
||||
def initialize(number, type_of_address: :international)
|
||||
self.number = number
|
||||
self.type_of_address = TypeOfAddress.new(type_of_address)
|
||||
end
|
||||
|
||||
def decode
|
||||
number.scan(/../).map(&:reverse).join.chomp('F')
|
||||
end
|
||||
|
||||
def length
|
||||
number.length - (number[-2, 2].hex >> 4 == 15 ? 1 : 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
module Biju
|
||||
module PDU
|
||||
class TypeOfAddress
|
||||
TYPE_OF_ADDRESS = {
|
||||
unknown: 0b10000001,
|
||||
international: 0b10010001,
|
||||
national: 0b10100001,
|
||||
reserved: 0b11110001,
|
||||
}
|
||||
|
||||
def initialize(type_of_address, options = {})
|
||||
unless type_of_address.is_a?(Symbol)
|
||||
type_of_address = type_of_address.hex if type_of_address.is_a?(String)
|
||||
type_of_address = TYPE_OF_ADDRESS.key(type_of_address)
|
||||
end
|
||||
@type_of_address = type_of_address
|
||||
end
|
||||
|
||||
def to_sym
|
||||
@type_of_address
|
||||
end
|
||||
|
||||
def hex
|
||||
TYPE_OF_ADDRESS[@type_of_address]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
module Biju
|
||||
module PDU
|
||||
class UserData
|
||||
ENCODING = {
|
||||
gsm7bit: GSM7Bit,
|
||||
ucs2: UCS2,
|
||||
}
|
||||
|
||||
attr_accessor :encoding, :message, :length
|
||||
|
||||
def self.encode(message, encoding: nil)
|
||||
encoding = DataCodingScheme.autodetect(message) if encoding.nil?
|
||||
|
||||
raise ArgumentError, 'Unknown encoding' unless ENCODING.has_key?(encoding)
|
||||
res = ENCODING[encoding].encode(message)
|
||||
|
||||
new(message: res[0], length: res[1][:length], encoding: encoding)
|
||||
end
|
||||
|
||||
def initialize(message: '', length: 0, encoding: :gsm7bit)
|
||||
self.encoding = DataCodingScheme.new(encoding)
|
||||
self.message = message
|
||||
self.length = length
|
||||
end
|
||||
|
||||
def decode
|
||||
ENCODING[encoding.to_sym].decode(message, length: length)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,15 +2,16 @@ require 'date'
|
|||
|
||||
module Biju
|
||||
class Sms
|
||||
attr_accessor :id, :phone_number, :message
|
||||
attr_accessor :id, :phone_number, :type_of_address, :message
|
||||
attr_reader :datetime
|
||||
|
||||
def self.from_pdu(string, id = nil)
|
||||
sms_infos = PDU.decode(string)
|
||||
new(id: id,
|
||||
phone_number: sms_infos[:sender_number],
|
||||
phone_number: sms_infos[:sender_number].decode,
|
||||
type_of_address: sms_infos[:sender_number].type_of_address.to_sym,
|
||||
datetime: sms_infos[:timestamp],
|
||||
message: sms_infos[:user_data])
|
||||
message: sms_infos[:user_data].decode)
|
||||
end
|
||||
|
||||
def initialize(params={})
|
||||
|
@ -35,6 +36,7 @@ module Biju
|
|||
end
|
||||
|
||||
def to_pdu
|
||||
Biju::PDU.encode(phone_number, message, type_of_address: type_of_address)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue