Class: Kinokero::Cloudprint

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

Overview

handles all interactions with Google Cloud Print server but not the jingle-XMPP related connections

Options

  • :url - GCP URL (as formed in constants above)

  • :oauth_token - supplied OAUTH from GCP

  • :ssl_ca_path - local SSL certificates path

  • :verbose - true if verbose logging

  • :log_truncate - true if truncate long responses from the log

  • :log_response - true if log responses from GCP

  • :client_redirect_uri - redirect URL for the same

Constant Summary collapse

GCP_CONTROL =

GCP API actions

'/control'
GCP_DELETE =
'/delete'
GCP_FETCH =
'/fetch'
GCP_LIST =
'/list'
GCP_REGISTER =
'/register'
GCP_UPDATE =
'/update'
GCP_ERR_XSRF_FAIL =

GCP ERROR CODES

9
GCP_ERR_NOT_REG_YET =

“XSRF token validation failed.”

502
GCP_ERR_NO_GET_AUTH =

“Token not registered yet.”

505
GCP_ERR_EXPIRED =

“Unable to get the authorization code.”

506
HTTP_RESPONSE_OK =

HTTP RESPONSE CODES

200
HTTP_RESPONSE_BAD_REQUEST =
400
HTTP_RESPONSE_UNAUTHORIZED =
401
HTTP_RESPONSE_FORBIDDEN =
403
HTTP_RESPONSE_NOT_FOUND =
404
GCP_JOBSTATES =

GCP Job States

%w(DRAFT HELD QUEUED IN_PROGRESS STOPPED DONE ABORTED)
GCP_JOBSTATE_DRAFT =

Job is being created and is not ready for processing yet.;

0
GCP_JOBSTATE_HELD =

Submitted and ready, but should not be processed yet.;

1
GCP_JOBSTATE_QUEUED =

Ready for processing.;

2
GCP_JOBSTATE_IN_PROGRESS =

Currently being processed.

3
GCP_JOBSTATE_STOPPED =

Was in progress, but stopped due to error or user intervention.;

4
GCP_JOBSTATE_DONE =

Processed successfully.;

5
GCP_JOBSTATE_ABORTED =

Aborted due to error or by user action (cancelled).;

6
GCP_USER_ACTIONS =

GCP User action causes

%(CANCELLED PAUSED OTHER)
GCP_USER_ACTION_CANCELLED =

User has cancelled the job

0
GCP_USER_ACTION_PAUSED =

User has paused the job

1
GCP_USER_ACTION_OTHER =

User has performed some other action

100
GCP_CONNECTION_STATE_READY =

GCP connection states

2
GCP_CONNECTION_STATE_NOT_READY =

“ONLINE”

3
DEFAULT_OPTIONS =

default options and configurations for cloudprinting

{
  :verbose => false,         # log everything?
  :auto_connect => true,    # automatically connect active devices?
  :log_truncate => false,   # truncate long responses?
  :log_response => false    # log the responses?
}
VALID_CLOUDPRINT_OPTIONS =

will be used to determine if user options valid if (in future) any default options were to be off-limits, then a specific sets of keys will have to be enumerated below

DEFAULT_OPTIONS.keys
@@connection =

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

nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(gcp_control, options) ⇒ Cloudprint

instantiate new CloudPrint object

  • Args :

    • gcp_control - nil or hash of persistent GCP attributes for managed printer

    • options - hash of optional settings (see above)

  • Returns :

    • CloudPrint object

  • Raises : -



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/kinokero/cloudprint.rb', line 108

def initialize( gcp_control, options )
  
  @options = validate_cloudprint_options( DEFAULT_OPTIONS.merge(options) )
  @gcp_control = validate_gcp_control( gcp_control ) 
  verbose = @options[:verbose]

  Cloudprint.make_client_connection( verbose ) # set up faraday connection

    # set up a reason why jingle not started
  gcp_control[:message] = "device inactive at initialization" unless gcp_control[:is_active]

  if gcp_control[:is_active]  &&
    printer_still_active?()  # verify that this printer is still active

    @jingle = Kinokero::Jingle.new( self, gcp_control, verbose ) 
  end  # if active printer

end

Instance Attribute Details

#connectionObject (readonly)

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



94
95
96
# File 'lib/kinokero/cloudprint.rb', line 94

def connection
  @connection
end

#gcp_controlObject (readonly)

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



94
95
96
# File 'lib/kinokero/cloudprint.rb', line 94

def gcp_control
  @gcp_control
end

#jingleObject (readonly)

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



94
95
96
# File 'lib/kinokero/cloudprint.rb', line 94

def jingle
  @jingle
end

Class Method Details

.client_connectionObject

returns the client-to-host faraday connection

  • Args : -

  • Returns :

    • Faraday connection object

  • Raises : -



139
140
141
142
# File 'lib/kinokero/cloudprint.rb', line 139

def self.client_connection( )
     # creates connection if first time; assumes verbose
  @@connection ||= make_client_connection( true )  
end

.gcp_anonymous_poll(anon_response) ⇒ Object


  • Args :

    • ++ -

    • ++ -

  • Returns : -

  • Raises : -



458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# File 'lib/kinokero/cloudprint.rb', line 458

def self.gcp_anonymous_poll(anon_response)

  poll_url = anon_response['polling_url'] + Kinokero.proxy_client_id
  printer_id = anon_response['printers'][0]['id']

    # countdown timer for polling loop
  0.step( anon_response['token_duration'].to_i, ::Kinokero.polling_secs ) do |i|

    sleep ::Kinokero.polling_secs    # sleep here until next poll

      # poll GCP to see if printer claimed yet?
    poll_response = gcp_poll_request( poll_url )

      # user claimed printer success ?
      # if reg_id == printer_id  ?????????
    return poll_response if 
      poll_response.body[ 'success' ] ||
      poll_response.body["errorCode"] != GCP_ERR_NOT_REG_YET

    #else, continue to poll

  end  # sleep/polling loop

    # log failure
  Kinokero::Log.debug( 'anon-poll' ) { "polling timed out" } if @options[:verbose]

  return { 'success' => false, 'message' =>  "polling timed out" }   # return failure

end

.gcp_anonymous_register(params) ⇒ Object

  • Args :

    • ++ -

    • ++ -

  • Returns : -

  • Raises : -



353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/kinokero/cloudprint.rb', line 353

def self.gcp_anonymous_register(params)

  sem_state = CloudDeviceState.new(
     version: "1.0",
     printer: PrinterStateSection.new( 
        state: "IDLE"
     )
  )

  reg_response =  Cloudprint.client_connection.post ::Kinokero.gcp_service + GCP_REGISTER do |req|
    req.headers['X-CloudPrint-Proxy'] = ::Kinokero.my_proxy_id 
    req.body =  {
      :name    => params[:gcp_printer_name],
      :proxy   => ::Kinokero.my_proxy_id,
      
      gcp_version:  '2.0',
      use_cdd:      'true',
      uuid:         params[:gcp_uuid],
      manufacturer: params[:gcp_manufacturer],
      model:        params[:gcp_model],
      setup_url:    params[:gcp_setup_url],
      support_url:  params[:gcp_support_url],
      update_url:   params[:gcp_update_url],
      firmware:     params[:gcp_firmware],

      semantic_state: sem_state.to_json,

      :capabilities => Faraday::UploadIO.new( 
                params[:capability_cdd], 
                ::Kinokero.mimetype_cdd 
      ),

    }

    Kinokero::Log.log_request( 'get anon-reg', req )

  end  # request do

  Kinokero::Log.log_response( 'anon-reg', reg_response )

  return reg_response

end

.gcp_anonymous_register_1_0(params) ⇒ Object

gcp_anonymous_register - /register gcp1.0 for anon printer; returns response hash DEPRECATED: older version



402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/kinokero/cloudprint.rb', line 402

def self.gcp_anonymous_register_1_0(params)

  reg_response =  Cloudprint.client_connection.post ::Kinokero.gcp_service + GCP_REGISTER do |req|
    req.headers['X-CloudPrint-Proxy'] = ::Kinokero.my_proxy_id 
    req.body =  {
      :name    => params[:gcp_printer_name],
      :proxy   => ::Kinokero.my_proxy_id,
      :description => params[:gcp_printer_name],
      :default_display_name => params[:gcp_printer_name],
      :status => params[:status],
      :capabilities => Faraday::UploadIO.new( 
                params[:capability_ppd], 
                ::Kinokero.mimetype_ppd 
      ),
    }

    Kinokero::Log.log_request( 'get anon-reg', req )

  end  # request do

  Kinokero::Log.log_response( 'anon-reg', reg_response )

  return reg_response

end

.gcp_get_oauth2_tokens(auth_code) ⇒ Object

  • Args :

    • auth_code -

    • ++ -

  • Returns :

    • oauth_response hash

  • Raises : -

From GCP documentation: the printer must use the authorization_code to obtain OAuth2 Auth tokens, themselves used to authenticate subsequent API calls to Google Cloud Print.

There are two types of tokens involved:

  • The refresh_token should be retained in printer memory forever. It can then be used to retrieve a temporary access_token.

  • The access_token needs to be refreshed every hour, and is used as authentication credentials in subsequent API calls.

The printer can initially retrieve both tokens together by POSTing the authorization_code to the OAuth2 token endpoint at accounts.google.com/o/oauth2/token,

along with the following parameters:

  • client_id (the same that you appended to polling_url when fetching the authorization_code)

  • redirect_uri (set it to ‘oob’)

  • client_secret (obtained along with client_id as part of your

  • client credentials)

  • grant_type=“authorization_code”

  • scope=www.googleapis.com/auth/cloudprint (scope identifies the Google service being accessed, in this case GCP)

If this request succeeds, a refresh token and short-lived access token will be returned via JSON. You can then use the access token to make API calls by attaching the following Authorization HTTP header to each of your API calls: Authorization: OAuth YOUR_ACCESS_TOKEN. You can retrieve additional access tokens once the first expires (after an hour) by using the token endpoint with your refresh token, client credentials, and the parameter grant_type=refresh_token.



554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
# File 'lib/kinokero/cloudprint.rb', line 554

def self.gcp_get_oauth2_tokens( auth_code )

  oauth_response = Cloudprint.client_connection.post( ::Kinokero.oauth2_token_endpoint ) do |req|
    req.body =  {
      :client_id =>  Kinokero.proxy_client_id,
      :client_secret =>  Kinokero.proxy_client_secret, 
      :redirect_uri => ::Kinokero.authorization_redirect_uri,
      :code => auth_code,
      :grant_type => "authorization_code",
      :scope => ::Kinokero.authorization_scope,
    }

    Kinokero::Log.log_request( 'get oauth2 code', req )
    
  end  # request do

  Kinokero::Log.log_response( 'oauth2 code', oauth_response )

  if oauth_response.status == HTTP_RESPONSE_OK

    oauth_response.body['success'] = true

  else  # failed to fetch token

    oauth_response.body['success'] = false
    Kinokero::Log.error( 'oauth2 token fetch fail' )  { "**********************************" }

  end  # if..then..else success

  return oauth_response

end

.gcp_poll_request(poll_url) ⇒ Object

gcp_poll_request – returns response hash after trying a polling POST

  • Args :

    • ++ -

    • ++ -

  • Returns : -

  • Raises : -



500
501
502
503
504
505
506
507
508
509
510
# File 'lib/kinokero/cloudprint.rb', line 500

def self.gcp_poll_request( poll_url )
      
  poll_response = Cloudprint.client_connection.post( poll_url ) do |req|  # connection poll request
    req.headers['X-CloudPrint-Proxy'] = ::Kinokero.my_proxy_id 
  end  # post poll response request

  Kinokero::Log.log_response( 'anon-poll', poll_response )

  return poll_response

end

.make_client_connection(verbose) ⇒ Object

sets up the client-to-host faraday connection

  • Args :

    • verbose: true if verbose debugging log output

  • Returns :

    • Faraday connection object

  • Raises : -

  • Note :

    • GCP returns responses as content-type: “text/plain”, so we want faraday to parse all responses from JSON to HASH regardless of content-type



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/kinokero/cloudprint.rb', line 157

def self.make_client_connection( verbose )

  @@connection = Faraday.new( 
        ::Kinokero.gcp_url, 
        :ssl => { :ca_path => ::Kinokero.ssl_ca_path }
  ) do |faraday|
    #   faraday.request  :retry
#       faraday.request  :oauth2, { 
#         :token     => @gcp_control[ :gcp_access_token ]
#       } 

    faraday.use      :cookie_jar       # cookiejar handling
    faraday.request  :multipart        # multipart files
    faraday.request  :url_encoded      # form-encode POST params
    faraday.response :json, { :content_type => [ /\bjson$/, /\bplain$/, /\btext$/ ]  }
    faraday.response(:logger) if verbose  #  log requests to STDOUT
    # faraday.adapter  :typhoeus         # make requests with typhoeus
    faraday.adapter Faraday.default_adapter # useful for debugging
  end # do faraday setup
  
end

.register_anonymous_printer(params, &block) ⇒ Object

handles the anonymous printer registration protocol

  • Args :

    • params - hash with parameters:

      • :id -

      • :printer_name -

      • :status - (of printer: string)

      • :capability_ppd - (filename)

      • :default_ppd - (filename)

    • block - asynchronously will receive oauth2 info if user submits token

  • Returns :

    • success/failure via response hash

      • :success - true or false

      • :swalapala_printer_id - any internal record id for the printer

      • :gcp_printer_name - string of printer name

      • :gcp_printer_id - gcp printer id for use in requests

      • :gcp_invite_page_url - gcp invite page url (see docs)

      • :gcp_easy_reg_url - gcp one-click url (see docs for complete_invite_url)

      • :gcp_auto_invite_url - gcp automated_invite_url (see docs)

      • :gcp_claim_token_url - gcp invite url (see docs)

      • :gcp_printer_reg_token - gcp registration_token for claiming printer

      • :gcp_reg_token_duration - gcp token_duration in seconds

  • Raises : -

Anonymous registration protocol

Anonymous registration requires registering without any login credentials, and then taking some of the returning tokens to complete the registration.

Here are the steps required:

  • Access registration URL using HTTPS without authentication tokens

  • Get token back from Cloud Print Service

  • Use the token to claim the printer (with authentication tokens)

  • Send query to polling URL;

  • receive an authentication_code, jabber_url

  • Send authentication_code together with our client_id, etc to oauth2

  • receive access_token, refresh_token

anonymous registration calls will return:

registration_token: a human readable string the user will need to claim printer ownership token_duration: the lifetime of the registration_token, in seconds (the whole registration has to finish within this time frame) invite_url: the url that a user will need to visit to claim ownership of the printer complete_invite_url: same thing of invite_url but already containing the registration_token, so that the user doesn’t have to insert it manually invite_page_url: the url of a printable page containing the user’s registration_token and url. (The page can be retrieved by the printer in PDF or PWG-raster format based on the HTTP header of the request, as for getting print jobs. At the moment the page size is letter and the resolution for the raster format is 300dpi. In the near future the page will have the page size and resolution based on the printer defaults.) polling_url: the url that the printer will need to poll for the OAuth2 authorization_code


Display to user following information to claim the user’s printer.

'Go claim your printer at this url:'
'http://www.google.com/cloudprint/claimprinter.html'
'Use token: response['registration_token']



237
238
239
240
241
242
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/kinokero/cloudprint.rb', line 237

def self.register_anonymous_printer(params,&block)

    # step 1: issue /register to GCP server
  reg_response = gcp_anonymous_register(params).body

  if (status = reg_response[ 'success' ])  # success; continues

    poll_thread = Thread.new do
    # DEPRECATED: pid = fork do
      # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      # step 3: poll GCP asynchronously as a separate process
      # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      poll_response = gcp_anonymous_poll(reg_response).body

      if poll_response[ 'success' ]  # successful polling registration

          # step 4, obtain OAuth2 authorization tokens
        oauth_response = gcp_get_oauth2_tokens( 
          poll_response[ 'authorization_code' ]
        ).body
        
#                  oauth_response['error'].nil?
#                  oauth_response['error'].to_s

            # create the control hash
          gcp_control = {
            printer_id:        params[:printer_id],
            gcp_printer_name:  reg_response['printers'][0]['name'],

            gcp_xmpp_jid:     poll_response['xmpp_jid'],
            gcp_printerid:    reg_response['printers'][0]['id'],
            gcp_owner_email:  poll_response['user_email'],

            gcp_confirmation_url:      poll_response['confirmation_page_url'],

            gcp_access_token:  oauth_response['access_token'],
            gcp_refresh_token: oauth_response['refresh_token'],
            gcp_token_type:    oauth_response['token_type'],

            gcp_token_expiry_time: Time.now + oauth_response['expires_in'].to_i,

            capability_ppd:  params[:capability_ppd],
            capability_cdd:  params[:capability_cdd],
            cups_alias:      params[:cups_alias],
            item:            params[:item],
            virgin_access:   true,  # boolean for dealing with jingle access token quirk
            is_active:       true,

            gcp_uuid:         params[:gcp_uuid],
            gcp_manufacturer: params[:gcp_manufacturer],
            gcp_model:        params[:gcp_model],
            gcp_setup_url:    params[:gcp_setup_url],
            gcp_support_url:  params[:gcp_support_url],
            gcp_update_url:   params[:gcp_update_url],
            gcp_firmware:     params[:gcp_firmware],

          }

          # let calling module save the response for us
        yield( gcp_control )  # persistence
  
      end  # if polling succeeded

      # DEPRECATED: exit
      # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    end  # fork block

      # force abort of everything if exception in thread
    poll_thread.abort_on_exception = true

    # DEPRECATED: Process.detach(pid) # we are not interested in the exit
    # code of this child and it should become independent
    
  end  # if successful response

    # continue on asynchronously with whatever
    # step 2: tell user where to claim printer
  response = {
    success:                 status, 
    message:                 reg_response['message'],
    swalapala_printer_id:    params[:printer_id],
    cups_alias:              params[:cups_alias] 
  }

  if status

    response[:gcp_printer_name]       = reg_response['printers'][0]['name']
    response[:gcp_printer_id]         = reg_response['printers'][0]['id']
    response[:gcp_invite_page_url]    = reg_response['invite_page_url']
    response[:gcp_easy_reg_url]       = reg_response['complete_invite_url']
    response[:gcp_auto_invite_url]    = reg_response['automated_invite_url']
    response[:gcp_claim_token_url]    = reg_response['invite_url']
    response[:gcp_printer_reg_token]  = reg_response['registration_token']
    response[:gcp_reg_token_duration] = reg_response['token_duration']

  end   # successful response

  return response
end

Instance Method Details

#gcp_delete_printer(skip_gcp = nil) ⇒ Object




716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
# File 'lib/kinokero/cloudprint.rb', line 716

def gcp_delete_printer( skip_gcp=nil )

  unless skip_gcp

  remove_response = Cloudprint.client_connection.post( ::Kinokero.gcp_service + GCP_DELETE ) do |req|
    req.headers['Authorization'] = gcp_form_auth_token()
    req.body =  {
      :printerid   => @gcp_control[:gcp_printerid]
    }

    log_request( 'remove printer', req )
    
  end  # request do
  log_response( 'remove printer', remove_response )

  end  # skip issuing gcp command

  if skip_gcp  ||  remove_response[ 'success' ]

    # unsubscribe & close jingle connection
    @jingle.gtalk_close_connection()  unless @jingle.nil?
    @gcp_control[:is_active] = false
    @jingle = nil   # make available to garbage collect

  end

  return skip_gcp  ||  remove_response.body

end

#gcp_form_auth_tokenObject

forms a fresh TOKEN_TYPE + AUTH_TOKEN string

  • Args : -

  • Returns :

    • string for current auth type & token

  • Raises : -



934
935
936
937
938
# File 'lib/kinokero/cloudprint.rb', line 934

def gcp_form_auth_token()
  return '' if @gcp_control.nil?
  gcp_refresh_tokens if Time.now >= @gcp_control[:gcp_token_expiry_time] 
  return "#{ @gcp_control[:gcp_token_type] } #{ @gcp_control[:gcp_access_token] }"
end

#gcp_form_jingle_auth_tokenObject

forms a fresh AUTH_TOKEN string

  • Args : -

  • Returns :

    • string for current auth token

  • Raises : -



951
952
953
954
955
956
957
958
959
960
961
962
963
# File 'lib/kinokero/cloudprint.rb', line 951

def gcp_form_jingle_auth_token()
  return '' if @gcp_control.nil?

    # jingle quirk seems to be unable to use the initial, long access token
    # which was returned by the oauth2 call (longer length)
    # but it jingle readily handles the refreshed access token (shorter length)
  if @gcp_control[:virgin_access] ||  
     Time.now >= @gcp_control[:gcp_token_expiry_time] 
    gcp_refresh_tokens 
  end

  return @gcp_control[:gcp_access_token]
end

#gcp_get_job_file(file_url) ⇒ Object

gcp_get_job_file – returns the job file to be printed

  • Args :

    • file_url - url to get the file for printing

  • Returns :

    • nil if failed to get file; else file itself

  • Raises : -



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
# File 'lib/kinokero/cloudprint.rb', line 622

def gcp_get_job_file( file_url )
      
  file_response = Cloudprint.client_connection.get( file_url ) do |req|  # connection get job file request
    req.headers['X-CloudPrint-Proxy'] = ::Kinokero.my_proxy_id 
    req.headers['Authorization'] = gcp_form_auth_token()

    log_request( 'get job file', req )
   end  # post poll response request

    # check the RESPONSE_HEADER for SUCCESS
  return ( file_response.env.status == HTTP_RESPONSE_OK  ?
              file_response.env.body  :
              nil
         )

end

#gcp_get_printer_fetch(printerid) ⇒ Object

gets a list of jobs queued for a printer

  • Args :

    • printerid - gcp printer_id for the printer

  • Returns :

    • fetch hash including queue

  • Raises : -



697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
# File 'lib/kinokero/cloudprint.rb', line 697

def gcp_get_printer_fetch( printerid )

  fetch_response = Cloudprint.client_connection.post( ::Kinokero.gcp_service + GCP_FETCH ) do |req|
    req.headers['Authorization'] = gcp_form_auth_token()
    req.body =  {
      :printerid   => printerid
    }

    log_request( 'fetch queue', req )
    
  end  # request do
  log_response( 'fetch queue', fetch_response )

  return fetch_response.body

end

#gcp_get_printer_listObject

gcp protocol to get the list of registered printers for the proxy

  • Args : -

  • Returns : -

  • Raises : -



906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
# File 'lib/kinokero/cloudprint.rb', line 906

def gcp_get_printer_list(  )

  list_response = Cloudprint.client_connection.post( ::Kinokero.gcp_service + GCP_LIST ) do |req|
    req.headers['Authorization'] = gcp_form_auth_token()
    req.body =  {
      :proxy   => ::Kinokero.my_proxy_id
    }

    log_request( 'get printer list', req )
    
  end  # request do
  log_response( 'get printer list', list_response )

  return list_response.body

end

#gcp_job_status(jobid, status, nbr_pages) ⇒ Object

report status for a print job

  • Args :

    • jobid - gcp job_id

    • status - GCP_JOBSTATUS_ type

    • nbr_pages - number of pages printed

  • Returns : -

  • Raises : -



759
760
761
762
763
764
765
766
767
768
# File 'lib/kinokero/cloudprint.rb', line 759

def gcp_job_status( jobid, status, nbr_pages )

  state_diff = PrintJobStateDiff.new(
    state: JobState.new( type: status ),
    pages_printed: nbr_pages
  )

  return generic_job_status( jobid, state_diff )

end

#gcp_job_status_abort(jobid, status, nbr_pages) ⇒ Object

report abort status for a print job

  • Args :

    • jobid - gcp job_id

    • status - GCP_USER_ACTION status

    • nbr_pages - number of pages printed

  • Returns : -

  • Raises : -



783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
# File 'lib/kinokero/cloudprint.rb', line 783

def gcp_job_status_abort( jobid, status, nbr_pages )

  state_diff = PrintJobStateDiff.new(
    state: JobState.new( 
            type: GCP_JOBSTATE_ABORTED,
            device_action_cause: DeviceActionCause.new( 
                    error_code: "DOWNLOAD_FAILURE"
            )                   
    ),
    pages_printed: nbr_pages
  )

  return generic_job_status( jobid, state_diff )

end

#gcp_ready_state_changed(ready_state, state, reason) ⇒ Object

version: “1.0”,

printer: PrinterStateSection.new( 
      state: "STOPPED",
      marker_state: MarkerState.new(
        item: [
          MarkerState::Item.new(
            vendor_id: "black",
            state: 'EXHAUSTED',
            level_percent: 0
          ),
          MarkerState::Item.new(
            vendor_id: "color",
            state: 'OK',
            level_percent: 88,
            level_pages: 100
          )
        ]
      )
)


821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'lib/kinokero/cloudprint.rb', line 821

def gcp_ready_state_changed( ready_state, state, reason )

    # TODO: screen out unexpected states
  #
  # state_diff will only show what has changed from previous CDS
  state_diff = CloudDeviceState.new(
     printer: PrinterStateSection.new( 
        state: state.to_s.upcase,
     )
  )

  status_response = Cloudprint.client_connection.post( ::Kinokero.gcp_service + GCP_UPDATE ) do |req|
    req.headers['Authorization'] = gcp_form_auth_token()
    req.body =  {
        printerid: @gcp_control[:gcp_printerid],
        semantic_state_diff: state_diff.to_json
    }

    log_request( 'device update', req )
    
  end  # request do

  log_response( 'device update', status_response )

  return status_response.body


end

#gcp_refresh_tokensObject

refresh an expired gcp auth token

  • Args : -

  • Returns :

    • oauth_response hash showing succcess/fail

  • Raises : -



651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
# File 'lib/kinokero/cloudprint.rb', line 651

def gcp_refresh_tokens( )

  oauth_response = Cloudprint.client_connection.post( ::Kinokero.oauth2_token_endpoint ) do |req|
    req.body =  {
      :client_id =>  Kinokero.proxy_client_id,
      :client_secret =>  Kinokero.proxy_client_secret, 
      :refresh_token => @gcp_control[:gcp_refresh_token],
      :grant_type => "refresh_token"
    }

    log_request( 'get refresh token', req )
    
  end  # request do

  if oauth_response.status == HTTP_RESPONSE_OK

    @gcp_control[:gcp_access_token] = oauth_response.body['access_token']
    @gcp_control[:gcp_token_expiry_time] = 
                Time.now + oauth_response.body['expires_in'].to_i
    @gcp_control[:virgin_access] = false
    oauth_response.body['success'] = true

  else  # failed to refresh token

    oauth_response.body['success'] = false
    Kinokero::Log.error( 'refresh fail' )  { "**********************************" }

  end  # if..then..else success

  log_response( 'refresh token', oauth_response )

  return oauth_response.body

end

#gtalk_start_connection(&block) ⇒ Object




595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
# File 'lib/kinokero/cloudprint.rb', line 595

def gtalk_start_connection(&block)

  if @jingle.nil?

    Kinokero::Log.error( "jingle not started yet; #{@gcp_control[:message]}" )

  else

    @jingle.gtalk_start_connection do |printerid|
      yield( printerid )
    end  # closure for doing print stuff

  end

end

#log_request(msg, req) ⇒ Object

log_request – will log the farady request params if verbose setting

  • Args :

    • msg - string to identify position in protocol sequence

    • req - gcp request hash

  • Returns : -

  • Raises : -



979
980
981
# File 'lib/kinokero/cloudprint.rb', line 979

def log_request( msg, req )
  Kinokero::Log.log_request( msg, req, @options[:verbose] )
end

#log_response(msg, response) ⇒ Object

log the GCP response

  • Args :

    • msg - string to identify position in protocol sequence

    • response - gcp response hash

  • Returns : -

  • Raises : -



995
996
997
998
999
1000
1001
# File 'lib/kinokero/cloudprint.rb', line 995

def log_response( msg, response )
  Kinokero::Log.log_response( 
      msg, 
      response,
      @options[:verbose] && @options[:log_response]  
  )
end

#printer_still_active?Boolean

checks GCP server to see if printer still active

  • Args : -

  • Returns :

    • true if still active; false if not

  • Raises : -

  • *side effects* :

    • changes :is_active status; sets :message for reason

Returns:

  • (Boolean)


863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
# File 'lib/kinokero/cloudprint.rb', line 863

def printer_still_active?()
  list_result = gcp_get_printer_list

  is_active = false  # assume failure

  if list_result["success"]

    if list_result["printers"].empty?

      @gcp_control[:message] = "proxy printer list empty"

      # try to find a matching printer in the list
    elsif list_result["printers"].any? { |p| p["id"] == @gcp_control[:gcp_printerid] }

      is_active = true   # success here!

    else  # failed to find matching printer in list

      @gcp_control[:message] = "matching printer not found in proxy printer list"

    end   # if..then..else check proxy printer list

  else  # failed to get list result

      @gcp_control[:message] = list_result["message"] || "couldn't obtain proxy printer list"

  end  # able/not get list results

  return (@gcp_control[:is_active] = is_active)

end