Class: Extface::Driver::EltradeTmU220

Inherits:
Base::Fiscal
  • Object
show all
Includes:
Extface::Driver::Eltrade::CommandsFp4
Defined in:
app/models/extface/driver/eltrade_tm_u220.rb

Defined Under Namespace

Classes: Frame, PrinterStatus

Constant Summary collapse

NAME =
'Eltrade TM-U220 (Serial)'.freeze
RESPONSE_TIMEOUT =

seconds

3
INVALID_FRAME_RETRIES =

count

6
BUSY_MAX_WAIT_CYCLES =

count

60
FLAG_TRUE =
"\xff\xff"
FLAG_FALSE =
"\x00\x00"

Instance Method Summary collapse

Instance Method Details

#add_comment(text) ⇒ Object



142
143
144
145
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 142

def add_comment(text)
  raise "Not in fiscal session" unless @fiscal_session
  send_comment text
end

#add_payment(value = nil, type_num = nil) ⇒ Object

0, 1, 2, 3



147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 147

def add_payment(value = nil, type_num = nil) # 0, 1, 2, 3
  raise "Not in fiscal session" unless @fiscal_session
  value_bytes = "\x00\x00\x00\x00" # recalculate
  unless value.nil?
    value_units = (value * 100).to_i # !FIXME
    value_bytes = "".b
    4.times{ |shift| value_bytes.insert 0, ((value_units >> shift*8) & 0xff).chr }
  end
  fsend Receipt::PRINT_RECEIPT, "" << (9 + (type_num || 0)).chr << value_bytes
  status = get_printer_status
end

#add_sale(sale_item) ⇒ Object



136
137
138
139
140
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 136

def add_sale(sale_item)
  raise "Not in fiscal session" unless @fiscal_session
  send_plu build_sale_data(sale_item)
  add_comment(sale_item.text2) if sale_item.text2.present?
end

#build_packet(cmd, data = "") ⇒ Object



210
211
212
213
214
215
216
217
218
219
220
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 210

def build_packet(cmd, data = "")
  "".tap() do |packet|
    packet << STRT.b
    packet << 0x00 #address
    packet << sequence_number
    packet << cmd
    packet << data.length
    packet << data.b
    packet << check_sum(packet[2..-1])
  end
end

#cancel_doc_session ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 95

def cancel_doc_session
  device.session("Doc cancel") do |s|
    s.notify "Doc Cancel Start"
    # cancel old one by open/close new one
    s.open_fiscal_doc
    s.close_fiscal_doc
    s.notify "Doc Cancel End"
  end
end

#check_status ⇒ Object



201
202
203
204
205
206
207
208
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 201

def check_status
  flush
  status = get_printer_status
  #TODO check for:
  #1. sold PLUs dangerously high -> solution PLU Report (0x32)
  #2. open bon and transaction count
  errors.empty?
end

#close_fiscal_doc ⇒ Object



130
131
132
133
134
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 130

def close_fiscal_doc
  raise "Not in fiscal session" unless @fiscal_session
  close_receipt
  @fiscal_session = false
end

#close_non_fiscal_doc ⇒ Object



116
117
118
119
120
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 116

def close_non_fiscal_doc
  raise "Not in print session" unless @print_session
  close_receipt
  @print_session = false
end

#fiscal_test ⇒ Object



52
53
54
55
56
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 52

def fiscal_test
  sale_and_pay_items_session([
    SaleItem.new( price: 0.01, text1: "Extface Test" )
  ])
end

#frecv(timeout) ⇒ Object

return RespFrame or nil



262
263
264
265
266
267
268
269
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 262

def frecv(timeout) # return RespFrame or nil
  if frame_bytes = pull(timeout)
    return Frame.new(frame_bytes.b)
  else
    errors.add :base, "No data received from device"
    return nil
  end
end

#fsend(cmd, data = "") ⇒ Object

return data or nil



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 222

def fsend(cmd, data = "") #return data or nil
  result = false
  status_invalid_responses = 0
  BUSY_MAX_WAIT_CYCLES.times do |retries|
    errors.clear
    push build_packet(Info::GET_STATUS)
    if stat_frame = frecv(RESPONSE_TIMEOUT)
      if stat_frame.valid?
        break if stat_frame.ready?
      else
        status_invalid_responses += 1
        if status_invalid_responses > INVALID_FRAME_RETRIES
          errors.add :base, "#{INVALID_FRAME_RETRIES} Broken Packets Received. Abort!"
          break
        end
      end
    end
    errors.add :base, "#{BUSY_MAX_WAIT_CYCLES} Busy Packets Received. Abort!"
  end
  return(result) if errors.any?
  
  packet_data = build_packet(cmd, data)
  INVALID_FRAME_RETRIES.times do |retries|
    errors.clear
    push packet_data
    if resp = frecv(RESPONSE_TIMEOUT)
      if resp.valid?
        result = resp.data
        break
      else
        resp.errors.full_messages.each do |msg|
          errors.add :base, msg
        end
      end
    end
    errors.add :base, "#{INVALID_FRAME_RETRIES} Broken Packets Received. Abort!"
  end
  return result
end

#get_printer_status ⇒ Object



197
198
199
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 197

def get_printer_status
  PrinterStatus.new(fsend(Info::GET_PRINTER_STATUS))
end

#handle(buffer) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 22

def handle(buffer)
  bytes_processed = 0
  if frame_match = buffer.match(/\xAA\x55.{3}(.{1}).*/nm) #m Treat \x0a as a character matched by .
    len = frame_match.captures.first.ord
    skip = frame_match.pre_match.length
    bytes_processed = skip + 7 + len # 6 pre + 1 check sum
    if bytes_processed <= buffer.length #packet in buffer
      rpush buffer[skip..bytes_processed]
    else
      bytes_processed = skip #not whole packet, just remove trail
    end
  end
  return bytes_processed
end

#non_fiscal_test ⇒ Object

tests



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 38

def non_fiscal_test
  device.session("Non Fiscal Text") do |s|
    s.notify "Printing Non Fiscal Text"
    s.open_non_fiscal_doc
    s.print "********************************"
    s.print "Extface Print Test".center(32)
    s.print "********************************"
    s.print ""
    s.print "Driver: " + "#{self.class::NAME}".truncate(24)
    s.close_non_fiscal_doc
    s.notify "Printing finished"
  end
end

#open_fiscal_doc(operator = '', password = '') ⇒ Object

fiscal



124
125
126
127
128
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 124

def open_fiscal_doc(operator = '', password = '')
  set_operatior(operator) if operator.present?
  open_receipt
  @fiscal_session = true
end

#open_non_fiscal_doc ⇒ Object

print



106
107
108
109
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 106

def open_non_fiscal_doc
  open_receipt Receipt::Variant::START_COMMENT_RECEIPT
  @print_session = true
end

#payed_recv_account(value = 0.00, payment_type_num = 0) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 164

def (value = 0.00, payment_type_num = 0)
  raise "Incorrect Amount Value" if value.zero?
  value_bytes = "\x00\x00\x00\x00" # recalculate
  unless value.nil?
    value_units = 0x100000000 + (value * 100).to_i # !FIXME
    value_bytes = "".b
    4.times{ |shift| value_bytes.insert 0, ((value_units >> shift*8) & 0xff).chr }
  end
  device.session("Payed Out / Received on Account (#{value.to_s})") do |s|
    s.notify "Payed / Received Start"
    fsend Other::, "" << (1 + payment_type_num).chr << value_bytes
    status = get_printer_status
    s.notify "Payed / Received End"
  end
end

#pbcd(byte) ⇒ Object



271
272
273
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 271

def pbcd(byte)
  ((byte / 10) << 4) | (byte % 10)
end

#period_report_session(from, to, detailed = true) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 77

def period_report_session(from, to, detailed = true)
  device.session("FP Report #{from.to_date.human} - #{to.to_date.human} (#{ detailed ? 'detailed' : 'short' })") do |s|
    dates_bytes = "".b
    dates_bytes << pbcd(from.day)
    dates_bytes << pbcd(from.month)
    dates_bytes << pbcd(from.year - 2000)
    dates_bytes << 0
    dates_bytes << pbcd(to.day)
    dates_bytes << pbcd(to.month)
    dates_bytes << pbcd(to.year - 2000)
    dates_bytes << 0
    s.notify "FP Report Start"
    s.fsend detailed ? Reports::FP_DETAILED_DATES : Reports::FP_GENERAL_DATES, dates_bytes
    status = s.get_printer_status
    s.notify "FP Report End"
  end
end


111
112
113
114
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 111

def print(text)
  raise "Not in print session" unless @print_session
  send_comment text
end

#sale_and_pay_items_session(items = [], operator = '', password = '') ⇒ Object

basket



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 181

def sale_and_pay_items_session(items = [], operator = '', password = '')
  device.session("Fiscal Doc") do |s|
    s.notify "Open Fiscal Receipt"
    s.open_fiscal_doc operator, password
    s.notify "Register Sale"
    items.each do |item|
      s.add_sale(item)
    end
    s.notify "Register Payment"
    s.total_payment
    s.notify "Close Fiscal Receipt"
    s.close_fiscal_doc
    s.notify "Fiscalization Completed!"
  end
end

#total_payment ⇒ Object



159
160
161
162
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 159

def total_payment
  raise "Not in fiscal session" unless @fiscal_session
  add_payment
end

#x_report_session ⇒ Object



68
69
70
71
72
73
74
75
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 68

def x_report_session
  device.session("X Report") do |s|
    s.notify "X Report Start"
    s.fsend Reports::DAILY_REPORT, FLAG_FALSE
    status = s.get_printer_status
    s.notify "X Report End"
  end
end

#z_report_session ⇒ Object

reports



59
60
61
62
63
64
65
66
# File 'app/models/extface/driver/eltrade_tm_u220.rb', line 59

def z_report_session
  device.session("Z Report") do |s|
    s.notify "Z Report Start"
    s.fsend Reports::DAILY_REPORT, FLAG_TRUE
    status = s.get_printer_status
    s.notify "Z Report End"
  end
end