Skip to content

Instantly share code, notes, and snippets.

@elektret
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elektret/f64155e1963e041554b5 to your computer and use it in GitHub Desktop.
Save elektret/f64155e1963e041554b5 to your computer and use it in GitHub Desktop.
ID 12d1:1001 Huawei Technologies
#!/usr/bin/env ruby
require 'rubygems'
require "serialport"
require 'optparse'
$:.unshift File.dirname(__FILE__)
require 'pdu'
module Medion
Baud = 115200
Parity = SerialPort::NONE
Flow = SerialPort::HARD
Data = 8
Stop = 1
class Umts
@@counter = 0
def initialize(device)
@sp = SerialPort.new device
@sp.baud = Medion::Baud
@sp.flow_control = Medion::Flow
@sp.data_bits = Medion::Data
@sp.stop_bits = Medion::Stop
@sp.read_timeout = 5000
if block_given?
value = yield self
@sp.close
exit value
end
end
def pin(string)
getok("AT+CPIN=#{string}")
end
def revision
getstr('AT+GMR')
end
def model
getstr('AT+GMM')
end
def manufacturer
getstr('AT+GMI')
end
def balance(command = '*100#', result = String.new)
return false unless getok("AT+CUSD=1,#{self.class.to_PDU(command)},15")
until (result = @sp.gets) =~ /CUSD/
timeout
end
self.class.from_PDU(self.class.hex2bin(result.split('"')[1]))
end
def close
@sp.close
end
def getok(string = nil, result = String.new)
@sp.puts "#{string}\r\r\n" unless string.nil?
until (result = @sp.gets) =~ /OK/
timeout
end
true
end
def getstr(command = 'AT+GMI', result = String.new)
@sp.puts "#{command}\r\r\n"
while (result = @sp.gets.strip) == command
timeout
end
until getok
timeout
end
result
end
def timeout
@@counter += 1
end
end
end
options = {
device: '/dev/ttyUSB0',
verbose: false,
balance: false
}
OptionParser.new do |opts|
opts.banner = "Usage: medion.rb [options]"
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
options[:verbose] = v
end
opts.on("-b", "--[no-]balance", "Print balance") do |b|
options[:balance] = b
end
opts.on("-d", "--device STRING", "Device file") do |d|
options[:device] = d
end
opts.on("-p", "--pin STRING", "Personal identification number") do |p|
options[:pin] = p
end
opts.on("-a", "--ascii STRING", "Convert ASCII") do |a|
options[:ascii] = a
end
opts.on("-u", "--pdu STRING", "Convert PDU") do |u|
options[:pdu] = u
end
end.parse!
unless options[:ascii].nil?
puts 'ASCII: ' + options[:ascii]
puts 'PDU: ' + Medion::Umts.to_PDU(options[:ascii])
exit 0
end
unless options[:pdu].nil?
puts 'ASCII: ' + Medion::Umts.from_PDU(Medion::Umts.hex2bin(options[:pdu]))
puts 'PDU: ' + options[:pdu]
exit 0
end
begin
Medion::Umts.new options[:device] do |stick|
if stick.getok('ATZ')
puts "#{options[:device]} responding ...\n\n"
puts 'Manufacturer: ' + stick.manufacturer
puts 'Model: ' + stick.model
puts 'Revision: ' + stick.revision + "\n\n"
else
puts "#{options[:device]} not responding. Exit"
next 1
end
unless options[:pin].nil?
if stick.pin(options[:pin])
puts 'PIN OK'
next 0
end
end
puts 'Balance: ' + stick.balance if options[:balance]
next 0
end
rescue
puts 'Something went wrong!'
puts 'Is ' + options[:device] + ' readable/writable?'
exit 1
end
# Converts ASCII to PDU and vise versa.
# perl -e '@a=split(//,unpack("b*","*100#")); for ($i=7; $i < $#a;
# $i+=8) { $a[$i]="" } print uc(unpack("H*", pack("b*", join("",
# @a))))."\n"'
# perl -e '@a=split(//,unpack("b*", pack("H*","AA180C3602"))); for
# ($i=6; $i < $#a; $i+=7) {$a[$i].="0" } print pack("b*", join("",
# @a)).""'
#
module Medion
class Umts
# Convert 8bit to 7bit
# *100# -> AA180C3602
def self.to_PDU(string, bytes = [])
result = String.new
string.each_char do |c|
byte = c.unpack('b8').first.split(//)
byte.pop
bytes << byte
end
bytes[0...bytes.length-1].each_with_index do |val, i|
(i+1).times { bytes[i].push(bytes[i+1].shift) }
end
bytes.join.chars.each_slice(8) do |byte|
result += "%02X" % [byte.join].pack('b8').ord
end
result.strip
end
# Convert 7bit to 8bit
# AA180C3602 -> *100#
def self.from_PDU(string, bytes = [])
result = String.new
string.each do |c|
byte = c.to_s(2).reverse.split(//)
byte.push('0') while byte.length < 8
bytes << byte
end
bytes.each_with_index do |val, i|
i.times { bytes[i].unshift(bytes[i-1].pop) }
end
bytes.join.chars.each_slice(7) do |byte|
result += "%c" % [byte.join].pack('b8').ord
end
result.strip
end
def self.hex2bin(s)
s.scan(/../).map { |x| x.hex }
end
end
end
# Example
# p to_PDU("*100#")
# p from_PDU(hex2bin("AA180C3602"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment