Class: Kinokero::Proxy

Inherits:
Object show all
Extended by:
Forwardable
Defined in:
lib/kinokero/proxy.rb

Overview

#########################################################################

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(gcp_hash, options = { verbose: true, auto_connect: true }) ⇒ Proxy




21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/kinokero/proxy.rb', line 21

def initialize( gcp_hash, options = { verbose: true, auto_connect: true } )

   @proxy_id   = Kinokero.my_proxy_id
   @options    = options
   @my_devices = {}   # will hold the device objects from seed

   Kinokero::Log.verbose_debug( options.inspect, options[:verbose] )
  
   cups_list = Cups.show_destinations  # current printer list

    # convert seed data into device objects
   gcp_hash.each_key do |item|
      
      # make sure that the persistent printer is still in CUPS list
     if cups_list.include?( gcp_hash[item][:cups_alias] )

        # instantiate object and remember
       @my_devices[ item ] = 
                Kinokero::Printer.new( gcp_hash[item] )

       @my_devices[ item ].cloudprint = Kinokero::Cloudprint.new( 
            @my_devices[item].gcp_printer_control, 
            options 
       )

     else  # previously registered device no longer active
       # TODO:
     end   # convert each seed to a device object

   end  # setting up each device

end

Instance Attribute Details

#my_devicesObject (readonly)

#########################################################################



16
17
18
# File 'lib/kinokero/proxy.rb', line 16

def my_devices
  @my_devices
end

#optionsObject (readonly)

#########################################################################



16
17
18
# File 'lib/kinokero/proxy.rb', line 16

def options
  @options
end

Instance Method Details

#do_connect(item) ⇒ Object


do_connect –




57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/kinokero/proxy.rb', line 57

def do_connect(item)
    # establish a jingle connection
  @my_devices[item].cloudprint.gtalk_start_connection do |printerid|
      # NOTE: this execution takes place asynchronously 
      # upon callback from jingle notification

    if printerid =~ /delete/
        # jingle notified us of delete
        # potentially reentreant; but delete anyway
        # TODO: verify printerid for us?
      do_delete( item, true )
    else   # print notification
      do_print_jobs( printerid )
    end   # if..then..else notification type

  end  # block

  # execution continues here BEFORE above block executes

    # upon first connect, fetch & print any pending jobs in queue
  fetch_and_print_queue_if_ready( 
        item, 
        @my_devices[item].gcp_printer_control[:gcp_printerid] 
  )

    # begin polling the printer device status
  @my_devices[item].start_poll_thread

end

#do_delete(item, skip_gcp = nil) ⇒ Object


do_delete – this is potentially reentreant: an initial do_delete spawns a jingle delete notification which then calls do delete again at an indeterminate point




103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/kinokero/proxy.rb', line 103

def do_delete(item, skip_gcp=nil )

      # forestall reentreant issues by checking our validity
  unless  (my_device = @my_devices[item]).nil?  

      # stop polling the printer device status
    my_device.stop_poll_thread

      # forestall reentreant issues by checking our validity
    unless  my_device.cloudprint.nil?
         # do delete housekeeping & maybe issue GCP command
      my_device.cloudprint.gcp_delete_printer( skip_gcp )
      my_device.cloudprint = nil    # release the reference to our object
    end   # unless cloudprint's been removed

  end  # unless device already removed

  @my_devices.delete( item )   # remove device struct from our list

end

#do_fetch_jobs(item) ⇒ Object




89
90
91
92
93
94
95
# File 'lib/kinokero/proxy.rb', line 89

def do_fetch_jobs( item )
  
  @my_devices[item].cloudprint.gcp_get_printer_fetch(
    @my_devices[item].gcp_printer_control[:gcp_printerid]
  )

end

#do_list(item) ⇒ Object





174
175
176
# File 'lib/kinokero/proxy.rb', line 174

def do_list(item)
  @my_devices[item].cloudprint.gcp_get_printer_list
end

#do_print_jobs(printerid) ⇒ Object

do_print_jobs blends across the perfect protocol boundaries I’m trying to maintain with Cloudprint, mainly because there’s a higher level process handling which it has to handle, thus involving multiple cloudprint interactions and Printer class interaction.




231
232
233
234
235
236
237
238
# File 'lib/kinokero/proxy.rb', line 231

def do_print_jobs( printerid )

  fetch_and_print_queue_if_ready( 
      item_from_printerid( printerid ), 
      printerid 
  )
  
end

#do_ready_state(item) ⇒ Object





180
181
182
183
184
185
186
# File 'lib/kinokero/proxy.rb', line 180

def do_ready_state(item)
  @my_devices[item].cloudprint.gcp_ready_state_changed( 
        true,   # shows ready for jobs
        0,  # waiting for work
        ''      # no reason description needed
  )
end

#do_refresh(item) ⇒ Object





167
168
169
170
# File 'lib/kinokero/proxy.rb', line 167

def do_refresh(item)
  @my_devices[item].cloudprint.gcp_refresh_tokens
  # new token should be set up in the gcp_control area
end

#do_register(gcp_request, &block) ⇒ Object


do_register – registers our default printer, prints claim info




127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/kinokero/proxy.rb', line 127

def do_register( gcp_request, &block )

  response = Kinokero::Cloudprint.register_anonymous_printer( gcp_request ) do |gcp_ctl|  

       # this block is called only if/when asynch polling completes
       # in a separate process
    puts Kinokero::Log.say_info("\n***** Printer successfully registered to GCP *****")
    puts Kinokero::Log.say_warn "register gcp_control: #{@gcp_ctl.object_id}"
    puts gcp_ctl.inspect

      # wrap the newly registered printer in a device object
    new_device =  Kinokero::Printer.new( gcp_ctl, gcp_request)

      # add it to our list of managed devices
    @my_devices[ gcp_ctl[:item] ] = new_device

      # create a cloudprint object to manage the protocols
    new_device.cloudprint = 
             Kinokero::Cloudprint.new( gcp_ctl, @options )

    Kinokero::Log.verbose_debug  "my_devices has #{ @my_devices.size } devices [#{ @my_devices.object_id }]"

      # this is the place to save anything we need to about the printers
      # under swalapala control; info is in gcp_ctl
    yield( gcp_ctl )  # persistence

  end  # block for register

  # execution continues here AFTER registering but BEFORE polling completes
  # this is our opportunity to tell the user to claim the printer via
  # registration token at Google Cloud Print server

  print_gcp_registration_info( response )  # output registration instructions

  return response

end

#fetch_and_print_queue_if_ready(item, printerid) ⇒ Object




207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/kinokero/proxy.rb', line 207

def fetch_and_print_queue_if_ready( item, printerid )

  if @my_devices[item].is_printer_ready?
  
    print_fetch_queue(
      item,    # find corresponding device item
      printerid,
      @my_devices[item].cloudprint.gcp_get_printer_fetch( printerid )
    )

  else   # oops, printer is NOT ready
    # TODO: shouldn't we tell GCP about this situation?

  end  # continue if printer ready

end

#item_from_printerid(printerid) ⇒ Object



Raises:



192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/kinokero/proxy.rb', line 192

def item_from_printerid( printerid )

  found = @my_devices.detect do |item, device|
    break item if device.gcp_printer_control[:gcp_printerid] == printerid
    false
  end  # each item

  raise PrinteridNotFound, printerid if found.nil?  # oops, not found!

  return found

end

DRY work of printing a fetch queue of jobs



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/kinokero/proxy.rb', line 243

def print_fetch_queue(item, printerid, fetch_result)
  if fetch_result['success']
    Kinokero::Log.verbose_debug  "#{ printerid } queue has #{ fetch_result['jobs'].size } jobs"

    my_cloudprint = @my_devices[item].cloudprint  # DRY access

      # deal with each job fetched
    fetch_result['jobs'].each do |job|

      unless printerid == job['printerid']  # ? hmmm, different printer ref'd

        item = item_from_printerid( printerid )  # find corresponding device item
        printerid = job['printerid']
        my_cloudprint = @my_devices[item].cloudprint  # DRY access
        print "\e[1;31m\n***** WARNING ***** differ printerid in fetch queue #{printerid}\n\e[0m" 
      end

        # able to download the job file for printing?
      if ( job_file = my_cloudprint.gcp_get_job_file( job["fileUrl"] ) )

          # update printer status to IN PROGRESS
        my_cloudprint.gcp_job_status(
          job["id"], 
          ::Kinokero::Cloudprint::GCP_JOBSTATE_IN_PROGRESS, 
          0
        )

          # write the file locally
        File.open( job["id"], 'wb') { |fp| fp.write(job_file) }
       
        status = @my_devices[item].print_file( job['id'] )

        # TODO: do something intelligent with the status
        # like report back to GCP

          # poll printer job status & report back to GCP
        my_cloudprint.gcp_job_status( 
          job["id"], 
          ::Kinokero::Cloudprint::GCP_JOBSTATE_DONE, 
          job["numberOfPages"] 
        )

          # delete the file
        File.delete( job["id"] )

      else  # failure to get file; tell GCP about the status
        my_cloudprint.gcp_job_status_abort( 
            job["id"], 
            ::Kinokero::Cloudprint::GCP_USER_ACTION_OTHER,
            0
        )
          
      end   # if..then..else get job file

    end   # do each job
  end  # pending job queue from fetch

end




304
305
306
307
308
309
310
311
# File 'lib/kinokero/proxy.rb', line 304

def print_gcp_registration_info( response )
  if response[:success]
    Kinokero::Printer.print_gcp_registration_info( 
      response[:cups_alias],   # actual printer to use
      snippet_registration_info( response )  # crafted message to print
    )
  end
end

#snippet_registration_info(response) ⇒ Object





315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/kinokero/proxy.rb', line 315

def snippet_registration_info( response )
<<RUBY10

******************************************************************
*** Important instructions to complete CloudPrint registration ***
******************************************************************
*** Go to the following url and claim printer with the given   ***
*** registration token, or click the easy-claim url below. You ***
*** must do this within the next fifteen (15) minutes. Thanks! ***
******************************************************************
 
Registration token: #{response[:gcp_printer_reg_token]}
Claim printer URL:  #{response[:gcp_claim_token_url]}
Easy-claim URL:     #{response[:gcp_easy_reg_url]}
Record id:          #{response[:swalapala_printer_id]}
Printer name:       #{response[:gcp_printer_name]}
GCP printer id:     #{response[:gcp_printer_id]}

RUBY10
end