da_funk 0.5.4 → 0.6.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -4
- data/README.md +159 -81
- data/RELEASE_NOTES.md +19 -0
- data/Rakefile +6 -0
- data/lib/da_funk/callback_flow.rb +50 -0
- data/lib/da_funk/file_parameter.rb +70 -0
- data/lib/da_funk/helper.rb +100 -35
- data/lib/da_funk/i18n.rb +77 -0
- data/lib/da_funk/i18n_error.rb +3 -0
- data/lib/da_funk/iso8583.rb +1 -0
- data/lib/da_funk/rake_task.rb +7 -1
- data/lib/da_funk/screen_flow.rb +30 -0
- data/lib/device.rb +1 -1
- data/lib/device/application.rb +75 -17
- data/lib/device/crypto.rb +2 -1
- data/lib/device/io.rb +5 -2
- data/lib/device/network.rb +12 -3
- data/lib/device/notification.rb +3 -3
- data/lib/device/params_dat.rb +102 -34
- data/lib/device/printer.rb +1 -1
- data/lib/device/setting.rb +6 -1
- data/lib/device/transaction/download.rb +11 -5
- data/lib/device/version.rb +1 -1
- data/lib/ext/string.rb +6 -0
- data/lib/file_db.rb +7 -3
- data/lib/iso8583/bitmap.rb +3 -6
- data/lib/iso8583/file_parser.rb +8 -10
- data/lib/iso8583/message.rb +9 -9
- data/lib/zip.rb +3 -3
- data/test/resources/shared/bitmap.dat +128 -0
- data/test/unit/iso8583_build_klass.rb +44 -0
- metadata +11 -2
data/lib/device/crypto.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
class Device
|
3
3
|
class Crypto
|
4
|
+
include DaFunk::Helper
|
4
5
|
CCITT_16 = [
|
5
6
|
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
6
7
|
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
@@ -40,7 +41,7 @@ class Device
|
|
40
41
|
crc = crc16(buf)
|
41
42
|
# to swap the number just invert the order of the indexes [0..1] and [2..3]
|
42
43
|
#"#{crc.to_s(16).rjust(4,"0")[0..1]}#{crc.to_s(16).rjust(4,"0")[2..3]}".upcase
|
43
|
-
crc.to_s(16).upcase
|
44
|
+
rjust(crc.to_s(16).upcase, 4, "0")
|
44
45
|
end
|
45
46
|
|
46
47
|
def self.crc16(buf, crc=0)
|
data/lib/device/io.rb
CHANGED
@@ -85,6 +85,8 @@ class Device
|
|
85
85
|
# @param max [Fixnum] Maximum length of the input string (127 bytes maximum).
|
86
86
|
# @param options [Hash]
|
87
87
|
#
|
88
|
+
# :value - Represent the current value, to be initially used.
|
89
|
+
#
|
88
90
|
# :precision - Sets the level of precision (defaults to 2).
|
89
91
|
#
|
90
92
|
# :separator - Sets the separator between the units (defaults to “.”).
|
@@ -109,7 +111,7 @@ class Device
|
|
109
111
|
# @return [String] buffer read from keyboard
|
110
112
|
def self.get_format(min, max, options = {})
|
111
113
|
set_default_format_option(options)
|
112
|
-
key = text = ""
|
114
|
+
key = text = options[:value] || ""
|
113
115
|
|
114
116
|
while key != CANCEL
|
115
117
|
Device::Display.clear options[:line]
|
@@ -117,7 +119,7 @@ class Device
|
|
117
119
|
key = getc
|
118
120
|
if key == BACK
|
119
121
|
text = text[0..-2]
|
120
|
-
elsif key == ENTER
|
122
|
+
elsif key == ENTER || key == KEY_TIMEOUT
|
121
123
|
return text
|
122
124
|
elsif key == F1 || key == DOWN || key == UP
|
123
125
|
change_next(text, check_mask_type(text, options))
|
@@ -176,6 +178,7 @@ class Device
|
|
176
178
|
def self.getc(timeout = self.timeout); super(timeout); end
|
177
179
|
|
178
180
|
def self.format(string, options)
|
181
|
+
options[:label].to_s +
|
179
182
|
if options[:mode] == IO_INPUT_MONEY || options[:mode] == IO_INPUT_DECIMAL
|
180
183
|
number_to_currency(string, options)
|
181
184
|
elsif options[:mode] == IO_INPUT_SECRET
|
data/lib/device/network.rb
CHANGED
@@ -61,8 +61,12 @@ class Device
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def self.connected?
|
64
|
-
|
65
|
-
|
64
|
+
if self.adapter.started? ||
|
65
|
+
(self.configured? && Device::Network.init(*self.config) == SUCCESS)
|
66
|
+
|
67
|
+
return adapter.connected?
|
68
|
+
end
|
69
|
+
NO_CONNECTION
|
66
70
|
end
|
67
71
|
|
68
72
|
def self.configured?
|
@@ -78,7 +82,11 @@ class Device
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def self.sim_id
|
81
|
-
adapter.sim_id
|
85
|
+
if adapter.respond_to? :sim_id
|
86
|
+
adapter.sim_id
|
87
|
+
else
|
88
|
+
""
|
89
|
+
end
|
82
90
|
end
|
83
91
|
|
84
92
|
# Check signal value
|
@@ -139,6 +147,7 @@ class Device
|
|
139
147
|
if ret == SUCCESS && (wifi? || ethernet?)
|
140
148
|
Device::Network.dhcp_client(20000)
|
141
149
|
end
|
150
|
+
Device::Setting.network_configured = 0 if ret != SUCCESS
|
142
151
|
end
|
143
152
|
ret
|
144
153
|
end
|
data/lib/device/notification.rb
CHANGED
@@ -41,7 +41,7 @@ class Device
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.start
|
44
|
-
if create_fiber? && Device::Network.connected?
|
44
|
+
if create_fiber? && Device::Network.connected? == Device::Network::SUCCESS
|
45
45
|
unless Device::Notification.current && Device::Notification.current.closed?
|
46
46
|
self.new(*self.config)
|
47
47
|
end
|
@@ -87,7 +87,7 @@ class Device
|
|
87
87
|
|
88
88
|
# Check if there is any notification
|
89
89
|
def check
|
90
|
-
if valid_check_interval? && Device::Network.connected?
|
90
|
+
if valid_check_interval? && Device::Network.connected? == Device::Network::SUCCESS
|
91
91
|
if @fiber.alive?
|
92
92
|
if (notification = @fiber.resume)
|
93
93
|
Notification.execute(NotificationEvent.new(notification))
|
@@ -152,7 +152,7 @@ class Device
|
|
152
152
|
conn.stream(subscription) { |ev| reply(conn, ev) }
|
153
153
|
end
|
154
154
|
true
|
155
|
-
rescue
|
155
|
+
rescue => exception
|
156
156
|
check_errors(exception)
|
157
157
|
end
|
158
158
|
end
|
data/lib/device/params_dat.rb
CHANGED
@@ -5,13 +5,14 @@ class Device
|
|
5
5
|
include Device::Helper
|
6
6
|
|
7
7
|
class << self
|
8
|
-
attr_accessor :file, :apps, :
|
8
|
+
attr_accessor :file, :apps, :valid, :files
|
9
9
|
end
|
10
10
|
|
11
11
|
self.apps = Array.new
|
12
|
+
self.files = Array.new
|
12
13
|
|
13
14
|
# To control if there is any app and parse worked
|
14
|
-
self.
|
15
|
+
self.valid = false
|
15
16
|
|
16
17
|
def self.file
|
17
18
|
self.setup unless @file
|
@@ -22,6 +23,47 @@ class Device
|
|
22
23
|
@file = FileDb.new(FILE_NAME)
|
23
24
|
end
|
24
25
|
|
26
|
+
def self.exists?
|
27
|
+
File.exists?(FILE_NAME)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.ready?
|
31
|
+
return unless exists?
|
32
|
+
apps.each {|app| return false if app.outdated? } if apps.size > 0
|
33
|
+
files.each {|f| return false if f.outdated? } if files.size > 0
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.parse_apps
|
38
|
+
new_apps = []
|
39
|
+
self.file["apps_list"].to_s.gsub("\"", "").split(";").each do |app|
|
40
|
+
label, name, type, crc = app.split(",")
|
41
|
+
if application = get_app(name)
|
42
|
+
application.crc = crc
|
43
|
+
else
|
44
|
+
application = Device::Application.new(label, name, type, crc)
|
45
|
+
end
|
46
|
+
new_apps << application
|
47
|
+
end
|
48
|
+
Device::Application.delete(@apps - new_apps)
|
49
|
+
@apps = new_apps
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.parse_files
|
53
|
+
new_files = []
|
54
|
+
self.file["files_list"].to_s.gsub("\"", "").split(";").each do |f|
|
55
|
+
name, crc = f.split(",")
|
56
|
+
if file_ = get_file(name)
|
57
|
+
file_.crc = crc
|
58
|
+
else
|
59
|
+
file_ = DaFunk::FileParameter.new(name, crc)
|
60
|
+
end
|
61
|
+
new_files << file_
|
62
|
+
end
|
63
|
+
Device::Application.delete(@files - new_files)
|
64
|
+
@files = new_files
|
65
|
+
end
|
66
|
+
|
25
67
|
# TODO Scalone: Change after @bmsatierf change the format
|
26
68
|
# For each apps on apps_list We'll have:
|
27
69
|
# Today: <label>,<arquivo>,<pages>,<crc>;
|
@@ -29,64 +71,85 @@ class Device
|
|
29
71
|
# Today: "1 - App,pc2_app.posxml,1,E0A0;"
|
30
72
|
# After: "1 - App,pc2_app.posxml,posxml,E0A0;"
|
31
73
|
# After: "1 - App,pc2_app.zip,ruby,E0A0;"
|
32
|
-
def self.
|
33
|
-
@apps = []
|
74
|
+
def self.parse
|
34
75
|
return unless self.setup
|
35
|
-
|
36
|
-
|
37
|
-
@apps << Device::Application.new(*app.split(","))
|
38
|
-
end
|
76
|
+
parse_apps
|
77
|
+
parse_files
|
39
78
|
|
40
79
|
if (@apps.size >= 1)
|
41
|
-
self.
|
80
|
+
self.valid = true
|
42
81
|
else
|
43
|
-
self.
|
82
|
+
self.valid = false
|
44
83
|
end
|
84
|
+
self.valid
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.get_app(name)
|
88
|
+
@apps.each {|app| return app if app.original == name }
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.get_file(name)
|
93
|
+
@files.each {|file_| return file_ if file_.original == name}
|
94
|
+
nil
|
45
95
|
end
|
46
96
|
|
47
97
|
def self.download
|
48
98
|
if attach
|
49
|
-
|
99
|
+
parse
|
100
|
+
ret = try(3) do |tried|
|
50
101
|
Device::Display.clear
|
51
|
-
|
52
|
-
puts "Parameters"
|
102
|
+
I18n.pt(:downloading_content, :args => ["PARAMS", 1, 1])
|
53
103
|
ret = Device::Transaction::Download.request_param_file(FILE_NAME)
|
54
104
|
check_download_error(ret)
|
55
105
|
end
|
56
|
-
|
57
|
-
|
106
|
+
parse if ret
|
107
|
+
ret
|
58
108
|
end
|
59
109
|
end
|
60
110
|
|
61
111
|
def self.update_apps(force = false)
|
62
|
-
if force || ! self.
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
112
|
+
self.download if force || ! self.valid
|
113
|
+
if self.valid
|
114
|
+
size_apps = @apps.size
|
115
|
+
@apps.each_with_index do |app, index|
|
116
|
+
self.update_app(app, index+1, size_apps)
|
117
|
+
end
|
118
|
+
|
119
|
+
size_files = @files.size
|
120
|
+
@files.each_with_index do |file_, index|
|
121
|
+
self.update_file(file_, index+1, size_files)
|
68
122
|
end
|
69
123
|
end
|
70
124
|
end
|
71
125
|
|
72
126
|
def self.format!
|
73
|
-
self.apps
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
Device::System.restart
|
127
|
+
Device::Application.delete(self.apps)
|
128
|
+
DaFunk::FileParameter.delete(self.files)
|
129
|
+
File.delete(FILE_NAME) if exists?
|
130
|
+
@apps = []
|
131
|
+
@files = []
|
79
132
|
end
|
80
133
|
|
81
|
-
def self.update_app(application)
|
134
|
+
def self.update_app(application, index = 1, all = 1, force = false)
|
82
135
|
if attach && application
|
83
136
|
try(3) do |tried|
|
84
137
|
Device::Display.clear
|
85
|
-
|
86
|
-
|
87
|
-
|
138
|
+
I18n.pt(:downloading_content, :args => [I18n.t(:apps), index, all])
|
139
|
+
ret = check_download_error(application.download(force))
|
140
|
+
sleep(1)
|
141
|
+
ret
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
88
145
|
|
89
|
-
|
146
|
+
def self.update_file(file_parameter, index = 1, all = 1, force = false)
|
147
|
+
if attach && file_parameter
|
148
|
+
try(3) do |tried|
|
149
|
+
Device::Display.clear
|
150
|
+
I18n.pt(:downloading_content, :args => [I18n.t(:files), index, all])
|
151
|
+
ret = check_download_error(file_parameter.download(force))
|
152
|
+
file_parameter.unzip if ret
|
90
153
|
sleep(1)
|
91
154
|
ret
|
92
155
|
end
|
@@ -94,13 +157,18 @@ class Device
|
|
94
157
|
end
|
95
158
|
|
96
159
|
def self.apps
|
97
|
-
self.
|
160
|
+
self.parse unless self.valid
|
98
161
|
@apps
|
99
162
|
end
|
100
163
|
|
164
|
+
def self.files
|
165
|
+
self.parse unless self.valid
|
166
|
+
@files
|
167
|
+
end
|
168
|
+
|
101
169
|
def self.executable_app
|
102
170
|
selected = self.executable_apps
|
103
|
-
if selected.size == 1
|
171
|
+
if selected && selected.size == 1
|
104
172
|
selected.first
|
105
173
|
end
|
106
174
|
end
|
data/lib/device/printer.rb
CHANGED
data/lib/device/setting.rb
CHANGED
@@ -43,11 +43,12 @@ class Device
|
|
43
43
|
"notification_stream_timeout" => "", # Time to wait stream message to read
|
44
44
|
"cw_switch_version" => "",
|
45
45
|
"cw_pos_timezone" => "",
|
46
|
-
"tcp_recv_timeout" => "
|
46
|
+
"tcp_recv_timeout" => "14",
|
47
47
|
"iso8583_recv_tries" => "0",
|
48
48
|
"iso8583_send_tries" => "0",
|
49
49
|
"crypto_dukpt_slot" => "",
|
50
50
|
"ctls" => "",
|
51
|
+
"locale" => "en",
|
51
52
|
"company_name" => ""
|
52
53
|
}
|
53
54
|
|
@@ -89,6 +90,10 @@ class Device
|
|
89
90
|
false
|
90
91
|
end
|
91
92
|
|
93
|
+
def self.update_attributes(*args)
|
94
|
+
@file.update_attributes(*args)
|
95
|
+
end
|
96
|
+
|
92
97
|
def self.method_missing(method, *args, &block)
|
93
98
|
setup unless @file
|
94
99
|
param = method.to_s
|
@@ -20,12 +20,12 @@ class Device
|
|
20
20
|
MAPREDUCE_RESPONSE_ERROR = -2
|
21
21
|
IO_ERROR = -3
|
22
22
|
|
23
|
-
def self.request_file(remote_path, local_path)
|
23
|
+
def self.request_file(remote_path, local_path, crc = "")
|
24
24
|
download = Device::Transaction::Download.new(Device::System.serial, "", Device.version)
|
25
25
|
download.perform(Device::Network.socket,
|
26
26
|
Device::Setting.company_name,
|
27
27
|
remote_path, local_path, Device::System.app,
|
28
|
-
Device::Setting.logical_number)
|
28
|
+
Device::Setting.logical_number, crc)
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.request_param_file(file = PARAMS_FILE)
|
@@ -44,8 +44,12 @@ class Device
|
|
44
44
|
# -1: Commnucation error
|
45
45
|
# -2: Mapreduce response error
|
46
46
|
# -3: IO Error
|
47
|
-
def perform(socket_proc, company_name, remote_path, filepath, current_app, logical_number, file_crc = nil)
|
48
|
-
|
47
|
+
def perform(socket_proc, company_name, remote_path, filepath, current_app, logical_number, file_crc = nil, socket_call = true)
|
48
|
+
if socket_call
|
49
|
+
@socket, @buffer, @request, @first_packet = socket_proc.call, "", "", ""
|
50
|
+
else
|
51
|
+
@socket, @buffer, @request, @first_packet = socket_proc, "", "", ""
|
52
|
+
end
|
49
53
|
@crc = file_crc ? file_crc : generate_crc(filepath)
|
50
54
|
key = "#{company_name}_#{remote_path}"
|
51
55
|
|
@@ -107,7 +111,9 @@ class Device
|
|
107
111
|
|
108
112
|
# receive 6A
|
109
113
|
@socket.read(1) if response_size > 1024
|
110
|
-
|
114
|
+
if socket_call
|
115
|
+
@socket.close unless @socket.closed?
|
116
|
+
end
|
111
117
|
|
112
118
|
return_code
|
113
119
|
end
|
data/lib/device/version.rb
CHANGED
data/lib/ext/string.rb
CHANGED
data/lib/file_db.rb
CHANGED
@@ -30,13 +30,17 @@ class FileDb
|
|
30
30
|
@hash.each do |line_key, line_value|
|
31
31
|
file_new.puts("#{line_key}=#{line_value}")
|
32
32
|
end
|
33
|
+
true
|
34
|
+
rescue
|
35
|
+
false
|
36
|
+
ensure
|
33
37
|
file_new.close
|
34
38
|
end
|
35
39
|
|
36
40
|
def []=(key, value)
|
37
41
|
value = value.to_s
|
38
|
-
old = @hash[key]
|
39
|
-
ret = @hash[key] = value
|
42
|
+
old = @hash[key.to_s]
|
43
|
+
ret = @hash[key.to_s] = value
|
40
44
|
save if old != value
|
41
45
|
ret
|
42
46
|
end
|
@@ -47,7 +51,7 @@ class FileDb
|
|
47
51
|
|
48
52
|
def update_attributes(values = Hash.new)
|
49
53
|
values.each do |key, value|
|
50
|
-
@hash[key] = value
|
54
|
+
@hash[key.to_s] = value.to_s
|
51
55
|
end
|
52
56
|
save
|
53
57
|
end
|
data/lib/iso8583/bitmap.rb
CHANGED
@@ -39,7 +39,7 @@ module ISO8583
|
|
39
39
|
# Set the bit to the indicated value. Only `true` sets the
|
40
40
|
# bit, any other value unsets it.
|
41
41
|
def []=(i, value)
|
42
|
-
if i > 128
|
42
|
+
if i > 128
|
43
43
|
raise ISO8583Exception.new("Bits > 128 are not permitted.")
|
44
44
|
elsif i < 2
|
45
45
|
raise ISO8583Exception.new("Bits < 2 are not permitted (continutation bit is set automatically)")
|
@@ -59,15 +59,12 @@ module ISO8583
|
|
59
59
|
|
60
60
|
# Generate the bytes representing this bitmap.
|
61
61
|
def to_bytes
|
62
|
-
|
63
|
-
# tricky and ugly, setting bit[1] only when generating to_s...
|
64
|
-
count = self[1] ? 128 : 64
|
65
|
-
arr.pack("B#{count}")
|
62
|
+
self.to_s.to_i(2).to_s(16).upcase
|
66
63
|
end
|
67
64
|
alias_method :to_b, :to_bytes
|
68
65
|
|
69
66
|
def to_hex
|
70
|
-
|
67
|
+
self.to_s.to_i(2).to_s(16).upcase.unpack("H*").first
|
71
68
|
end
|
72
69
|
|
73
70
|
# Generate a String representation of this bitmap in the form:
|