diff --git a/drivers/qbic/touch_panel.cr b/drivers/qbic/touch_panel.cr new file mode 100644 index 00000000000..b2cc1fb3505 --- /dev/null +++ b/drivers/qbic/touch_panel.cr @@ -0,0 +1,82 @@ +require "uri" + +module Qbic; end + +class Qbic::TouchPanel < PlaceOS::Driver + descriptive_name "Qbic Touch Panel" + generic_name :Display + + default_settings({ + username: "admin", + password: "12345678", + }) + + @username : String = "" + @password : String = "" + @auth_token : String = "" + @auth_expiry : Time = 1.minute.ago + + def on_load + on_update + end + + def on_update + @username = URI.encode_www_form setting(String, :username) + @password = URI.encode_www_form setting(String, :password) + end + + class AuthResponse + include JSON::Serializable + + # Returned on success + property access_token : String + property refresh_token : String + property token_type : String + + # Returned on failure + property detail : String? + end + + def expire_token! + @auth_expiry = 1.minute.ago + end + + def token_expired? + now = Time.utc + @auth_expiry < now + end + + def get_token + return @auth_token unless token_expired? + + response = post("/v1/oauth2/token", + body: { + "grant_type" => "password", + "username" => @username, + "password" => @password + }.to_json, + headers: { + "Content-Type" => "application/json" + } + ) + + data = response.body.not_nil! + logger.debug { "received login response #{data}" } + + if response.success? + resp = AuthResponse.from_json(data) + logger.debug { "resp" } + logger.debug { resp.inspect } + @auth_token = "#{resp.token_type} #{resp.access_token}" + else + case response.status_code + when 400 + resp = AuthResponse.from_json(data) + logger.warn { resp.detail } + else + logger.error { "authentication failed with HTTP #{response.status_code}" } + end + raise "failed to obtain access token" + end + end +end diff --git a/drivers/qbic/touch_panel_spec.cr b/drivers/qbic/touch_panel_spec.cr new file mode 100644 index 00000000000..a7a340dc119 --- /dev/null +++ b/drivers/qbic/touch_panel_spec.cr @@ -0,0 +1,25 @@ +DriverSpecs.mock_driver "Qbic::TouchPanel" do + # Send the request + retval = exec(:get_token) + + # We should request a new token from Floorsense + expect_http_request do |request, response| + if io = request.body + data = io.gets_to_end + request = JSON.parse(data) + + if request["grant_type"] == "password" && request["username"] == "admin" && request["password"] == "12345678" + response.status_code = 200 + response.output.puts %({"access_token":"t6pm11le6m6pvae18ar9jqdap4","refresh_token":"gq5c6p1lps3m24nf1th0cmda32","token_type":"Bearer"}) + else + response.status_code = 400 + response.output.puts %({"detail":"Invalid_client, make sure username and password is correct."}) + end + else + raise "expected request to include username and password" + end + end + + # What the function should return (for use in making further requests) + retval.get.should eq("Bearer t6pm11le6m6pvae18ar9jqdap4") +end