{"action":"created","comment":{"url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/comments/49531520","id":49531520,"diff_hunk":"@@ -0,0 +1,203 @@\n+package com.bypassmobile.peripherals.bematechldx9000;\n+\n+import android.hardware.usb.UsbDevice;\n+import android.hardware.usb.UsbDeviceConnection;\n+import android.hardware.usb.UsbManager;\n+import android.net.Uri;\n+import android.os.Handler;\n+import android.os.Looper;\n+\n+import com.bypassmobile.peripherals.bematechldx9000.api.PoleDisplay;\n+import com.bypassmobile.peripherals.deviceinfo.DeviceInfoManager;\n+import com.hoho.android.usbserial.driver.UsbSerialDriver;\n+import com.hoho.android.usbserial.driver.UsbSerialPort;\n+\n+import java.io.IOException;\n+import java.util.Observable;\n+import java.util.Observer;\n+\n+public class UsbCustomerDisplay extends Observable implements PoleDisplay {\n+    private static final int DELAY_TIME = 2500;\n+\n+    private UsbManager mUsbManager;\n+    private UsbDevice mUsbDevice;\n+    private UsbSerialDriver mUsbSerialDriver;\n+    private UsbSerialPort mUsbSerialPort;\n+    private UsbDeviceConnection mUsbDeviceConnection;\n+\n+    UsbCustomerDisplay(UsbManager manager, UsbDevice device, Observer observer) {\n+        mUsbManager = manager;\n+        mUsbDevice = device;\n+\n+        if (mUsbManager == null) {\n+            throw new IllegalArgumentException(\"UsbCustomerDisplay cannot be initialized with a null UsbManager\");\n+        }\n+\n+        if (mUsbDevice == null) {\n+            throw new IllegalArgumentException(\"UsbCustomerDisplay cannot be initialized with a null UsbDevice\");\n+        }\n+\n+        mUsbSerialDriver = UsbSerialDriverFactory.getDriverForUsbDisplay(mUsbManager, device);\n+        if (mUsbSerialDriver == null) {\n+            throw new IllegalStateException(\"USB Serial Device driver not found. Cannot instantiate UsbCustomerFacingDisplay\");\n+        }\n+\n+        DeviceInfoManager.inst().getInfoFor(device);\n+        addObserver(observer);\n+        initConnection();\n+    }\n+\n+    private void initConnection() {\n+        initConnectionSettings();\n+        try {\n+            mUsbSerialPort.open(mUsbDeviceConnection);\n+            UsbDeviceCommands.configDisplay(mUsbSerialPort, false);\n+            sendEvent(new CustomerDisplayConnectedEvent(this));\n+        } catch (IOException ioe) {\n+            try {\n+                mUsbSerialPort.close();\n+                mUsbSerialPort = null;\n+            } catch (IOException e) {\n+                e.printStackTrace();\n+            }\n+\n+            mUsbSerialPort = null;\n+            sendEvent(new CustomerDisplayDisconnectedEvent(null));\n+            throw new IllegalStateException(\"IOException upon opening connection.\");\n+        }\n+    }\n+\n+    private void initConnectionSettings() {\n+        if (mUsbSerialDriver.getPorts().size() == 0) {\n+            throw new IllegalStateException(\"UsbDriver has no ports.\");\n+        }\n+\n+        mUsbSerialPort = mUsbSerialDriver.getPorts().get(0);\n+\n+        mUsbDeviceConnection = mUsbManager.openDevice(mUsbSerialDriver.getDevice());\n+        if (mUsbDeviceConnection == null) {\n+            throw new IllegalStateException(\"Cannot use device without a connection\");\n+        }\n+    }\n+\n+    private void sendEvent(Object data) {\n+        setChanged();\n+        notifyObservers(data);\n+    }\n+\n+    @Override\n+    public void toggleCursor(boolean showCursor) {\n+        try {\n+            UsbDeviceCommands.showCursor(mUsbSerialPort, showCursor);\n+        } catch (IOException e) {\n+            e.printStackTrace();\n+        }\n+    }\n+\n+    @Override\n+    public void backspace() {\n+        UsbDeviceCommands.backspace(mUsbSerialPort);\n+    }\n+\n+    @Override\n+    public void clearAllText() {\n+        UsbDeviceCommands.clearAllText(mUsbSerialPort);\n+    }\n+\n+    @Override\n+    public void zeroBalance() {\n+        Handler handler = new Handler(Looper.getMainLooper());\n+        Runnable runnable = new Runnable() {\n+            public void run() {\n+                UsbDeviceCommands.writeThankYou(mUsbSerialPort);\n+                clearDisplayAfterDelay(DELAY_TIME);\n+            }\n+        };\n+        handler.postDelayed(runnable, 1000);\n+\n+    }\n+\n+    @Override\n+    public void paymentDeclined() {\n+        UsbDeviceCommands.writePaymentDeclined(mUsbSerialPort);\n+    }\n+\n+    @Override\n+    public void paymentDeclined(Uri orderUri) {\n+        UsbDeviceCommands.writePaymentDeclined(mUsbSerialPort);\n+    }\n+\n+    @Override\n+    public void discountApplied() {\n+        UsbDeviceCommands.writeDiscountApplied(mUsbSerialPort);\n+    }\n+\n+    @Override\n+    public void writeLineItem(String name, String price, String quantity) {\n+        UsbDeviceCommands.writeLineItem(mUsbSerialPort, name);\n+        UsbDeviceCommands.writeLineItemPriceToBottomLine(mUsbSerialPort, price, quantity);\n+    }\n+\n+    @Override\n+    public void writeChangeDue(String changeDue) {\n+        UsbDeviceCommands.writeChangeDueToTopLine(mUsbSerialPort, changeDue);\n+    }\n+\n+    @Override\n+    public void writeAmountDue(String amountDue) {\n+        UsbDeviceCommands.writeAmountDueToBottomLine(mUsbSerialPort, amountDue);\n+    }\n+\n+    @Override\n+    public void writeTotals(String subtotal, String total) {\n+        UsbDeviceCommands.writeSubtotalToTopLine(mUsbSerialPort, subtotal);\n+        UsbDeviceCommands.writeTotalToBottomLine(mUsbSerialPort, total);\n+    }\n+\n+    @Override\n+    public String getDeviceInfo() {\n+        if (mUsbDevice != null) {\n+            int vendorId = mUsbDevice.getVendorId();\n+            int productId = mUsbDevice.getProductId();\n+\n+            if (vendorId == 4008 && productId == 41104) {","path":"bematechldx9000/src/main/java/com/bypassmobile/peripherals/bematechldx9000/UsbCustomerDisplay.java","position":163,"original_position":163,"commit_id":"7bda0fed2612be5f73dee804bac4603d9273f787","original_commit_id":"7bda0fed2612be5f73dee804bac4603d9273f787","user":{"login":"ryansgot","id":4745799,"avatar_url":"https://avatars.githubusercontent.com/u/4745799?v=3","gravatar_id":"","url":"https://api.github.com/users/ryansgot","html_url":"https://github.com/ryansgot","followers_url":"https://api.github.com/users/ryansgot/followers","following_url":"https://api.github.com/users/ryansgot/following{/other_user}","gists_url":"https://api.github.com/users/ryansgot/gists{/gist_id}","starred_url":"https://api.github.com/users/ryansgot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ryansgot/subscriptions","organizations_url":"https://api.github.com/users/ryansgot/orgs","repos_url":"https://api.github.com/users/ryansgot/repos","events_url":"https://api.github.com/users/ryansgot/events{/privacy}","received_events_url":"https://api.github.com/users/ryansgot/received_events","type":"User","site_admin":false},"body":"I'm not going to stop ship for this, but the deviceinfo library is intended to be used for communicating information about a device. You can access the information about your USB device by calling:\r\n```java\r\nUsbDeviceInfo deviceInfo = DeviceInfoManager.inst().getInfoFor(mUsbDevice);\r\n```\r\nThe ```DeviceInfoManager``` singleton is going to know about your devices because it parses the XML resource that you used to initialize it. This separates the configuration of details of the devices from the implementation details of using them (a good thing).","created_at":"2016-01-12T23:32:36Z","updated_at":"2016-01-12T23:32:36Z","html_url":"https://github.com/bypasslane/android-customer-display/pull/1#discussion_r49531520","pull_request_url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/comments/49531520"},"html":{"href":"https://github.com/bypasslane/android-customer-display/pull/1#discussion_r49531520"},"pull_request":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1","id":55631963,"html_url":"https://github.com/bypasslane/android-customer-display/pull/1","diff_url":"https://github.com/bypasslane/android-customer-display/pull/1.diff","patch_url":"https://github.com/bypasslane/android-customer-display/pull/1.patch","issue_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues/1","number":1,"state":"open","locked":false,"title":"Create library for cfd","user":{"login":"mckinleymax","id":1403955,"avatar_url":"https://avatars.githubusercontent.com/u/1403955?v=3","gravatar_id":"","url":"https://api.github.com/users/mckinleymax","html_url":"https://github.com/mckinleymax","followers_url":"https://api.github.com/users/mckinleymax/followers","following_url":"https://api.github.com/users/mckinleymax/following{/other_user}","gists_url":"https://api.github.com/users/mckinleymax/gists{/gist_id}","starred_url":"https://api.github.com/users/mckinleymax/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mckinleymax/subscriptions","organizations_url":"https://api.github.com/users/mckinleymax/orgs","repos_url":"https://api.github.com/users/mckinleymax/repos","events_url":"https://api.github.com/users/mckinleymax/events{/privacy}","received_events_url":"https://api.github.com/users/mckinleymax/received_events","type":"User","site_admin":false},"body":"Created a library that will allow for cfd integration with Access. At this time the only supported device is the Bematech LDX9000UP but this is a starting point for other future cfd devices.","created_at":"2016-01-11T15:00:21Z","updated_at":"2016-01-12T23:32:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7da8f6b8c23376032affd5e9c2180e375a0e7505","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1/commits","review_comments_url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1/comments","review_comment_url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues/1/comments","statuses_url":"https://api.github.com/repos/bypasslane/android-customer-display/statuses/7bda0fed2612be5f73dee804bac4603d9273f787","head":{"label":"bypasslane:feature/library","ref":"feature/library","sha":"7bda0fed2612be5f73dee804bac4603d9273f787","user":{"login":"bypasslane","id":527428,"avatar_url":"https://avatars.githubusercontent.com/u/527428?v=3","gravatar_id":"","url":"https://api.github.com/users/bypasslane","html_url":"https://github.com/bypasslane","followers_url":"https://api.github.com/users/bypasslane/followers","following_url":"https://api.github.com/users/bypasslane/following{/other_user}","gists_url":"https://api.github.com/users/bypasslane/gists{/gist_id}","starred_url":"https://api.github.com/users/bypasslane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bypasslane/subscriptions","organizations_url":"https://api.github.com/users/bypasslane/orgs","repos_url":"https://api.github.com/users/bypasslane/repos","events_url":"https://api.github.com/users/bypasslane/events{/privacy}","received_events_url":"https://api.github.com/users/bypasslane/received_events","type":"Organization","site_admin":false},"repo":{"id":48125932,"name":"android-customer-display","full_name":"bypasslane/android-customer-display","owner":{"login":"bypasslane","id":527428,"avatar_url":"https://avatars.githubusercontent.com/u/527428?v=3","gravatar_id":"","url":"https://api.github.com/users/bypasslane","html_url":"https://github.com/bypasslane","followers_url":"https://api.github.com/users/bypasslane/followers","following_url":"https://api.github.com/users/bypasslane/following{/other_user}","gists_url":"https://api.github.com/users/bypasslane/gists{/gist_id}","starred_url":"https://api.github.com/users/bypasslane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bypasslane/subscriptions","organizations_url":"https://api.github.com/users/bypasslane/orgs","repos_url":"https://api.github.com/users/bypasslane/repos","events_url":"https://api.github.com/users/bypasslane/events{/privacy}","received_events_url":"https://api.github.com/users/bypasslane/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bypasslane/android-customer-display","description":"","fork":false,"url":"https://api.github.com/repos/bypasslane/android-customer-display","forks_url":"https://api.github.com/repos/bypasslane/android-customer-display/forks","keys_url":"https://api.github.com/repos/bypasslane/android-customer-display/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bypasslane/android-customer-display/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bypasslane/android-customer-display/teams","hooks_url":"https://api.github.com/repos/bypasslane/android-customer-display/hooks","issue_events_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues/events{/number}","events_url":"https://api.github.com/repos/bypasslane/android-customer-display/events","assignees_url":"https://api.github.com/repos/bypasslane/android-customer-display/assignees{/user}","branches_url":"https://api.github.com/repos/bypasslane/android-customer-display/branches{/branch}","tags_url":"https://api.github.com/repos/bypasslane/android-customer-display/tags","blobs_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/refs{/sha}","trees_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bypasslane/android-customer-display/statuses/{sha}","languages_url":"https://api.github.com/repos/bypasslane/android-customer-display/languages","stargazers_url":"https://api.github.com/repos/bypasslane/android-customer-display/stargazers","contributors_url":"https://api.github.com/repos/bypasslane/android-customer-display/contributors","subscribers_url":"https://api.github.com/repos/bypasslane/android-customer-display/subscribers","subscription_url":"https://api.github.com/repos/bypasslane/android-customer-display/subscription","commits_url":"https://api.github.com/repos/bypasslane/android-customer-display/commits{/sha}","git_commits_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/commits{/sha}","comments_url":"https://api.github.com/repos/bypasslane/android-customer-display/comments{/number}","issue_comment_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues/comments{/number}","contents_url":"https://api.github.com/repos/bypasslane/android-customer-display/contents/{+path}","compare_url":"https://api.github.com/repos/bypasslane/android-customer-display/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bypasslane/android-customer-display/merges","archive_url":"https://api.github.com/repos/bypasslane/android-customer-display/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bypasslane/android-customer-display/downloads","issues_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues{/number}","pulls_url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls{/number}","milestones_url":"https://api.github.com/repos/bypasslane/android-customer-display/milestones{/number}","notifications_url":"https://api.github.com/repos/bypasslane/android-customer-display/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bypasslane/android-customer-display/labels{/name}","releases_url":"https://api.github.com/repos/bypasslane/android-customer-display/releases{/id}","created_at":"2015-12-16T17:50:43Z","updated_at":"2015-12-16T19:34:51Z","pushed_at":"2016-01-12T21:52:46Z","git_url":"git://github.com/bypasslane/android-customer-display.git","ssh_url":"git@github.com:bypasslane/android-customer-display.git","clone_url":"https://github.com/bypasslane/android-customer-display.git","svn_url":"https://github.com/bypasslane/android-customer-display","homepage":null,"size":148,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"bypasslane:master","ref":"master","sha":"4d560a37a16de44b752c4e5460523db92bc2be19","user":{"login":"bypasslane","id":527428,"avatar_url":"https://avatars.githubusercontent.com/u/527428?v=3","gravatar_id":"","url":"https://api.github.com/users/bypasslane","html_url":"https://github.com/bypasslane","followers_url":"https://api.github.com/users/bypasslane/followers","following_url":"https://api.github.com/users/bypasslane/following{/other_user}","gists_url":"https://api.github.com/users/bypasslane/gists{/gist_id}","starred_url":"https://api.github.com/users/bypasslane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bypasslane/subscriptions","organizations_url":"https://api.github.com/users/bypasslane/orgs","repos_url":"https://api.github.com/users/bypasslane/repos","events_url":"https://api.github.com/users/bypasslane/events{/privacy}","received_events_url":"https://api.github.com/users/bypasslane/received_events","type":"Organization","site_admin":false},"repo":{"id":48125932,"name":"android-customer-display","full_name":"bypasslane/android-customer-display","owner":{"login":"bypasslane","id":527428,"avatar_url":"https://avatars.githubusercontent.com/u/527428?v=3","gravatar_id":"","url":"https://api.github.com/users/bypasslane","html_url":"https://github.com/bypasslane","followers_url":"https://api.github.com/users/bypasslane/followers","following_url":"https://api.github.com/users/bypasslane/following{/other_user}","gists_url":"https://api.github.com/users/bypasslane/gists{/gist_id}","starred_url":"https://api.github.com/users/bypasslane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bypasslane/subscriptions","organizations_url":"https://api.github.com/users/bypasslane/orgs","repos_url":"https://api.github.com/users/bypasslane/repos","events_url":"https://api.github.com/users/bypasslane/events{/privacy}","received_events_url":"https://api.github.com/users/bypasslane/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bypasslane/android-customer-display","description":"","fork":false,"url":"https://api.github.com/repos/bypasslane/android-customer-display","forks_url":"https://api.github.com/repos/bypasslane/android-customer-display/forks","keys_url":"https://api.github.com/repos/bypasslane/android-customer-display/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bypasslane/android-customer-display/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bypasslane/android-customer-display/teams","hooks_url":"https://api.github.com/repos/bypasslane/android-customer-display/hooks","issue_events_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues/events{/number}","events_url":"https://api.github.com/repos/bypasslane/android-customer-display/events","assignees_url":"https://api.github.com/repos/bypasslane/android-customer-display/assignees{/user}","branches_url":"https://api.github.com/repos/bypasslane/android-customer-display/branches{/branch}","tags_url":"https://api.github.com/repos/bypasslane/android-customer-display/tags","blobs_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/refs{/sha}","trees_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bypasslane/android-customer-display/statuses/{sha}","languages_url":"https://api.github.com/repos/bypasslane/android-customer-display/languages","stargazers_url":"https://api.github.com/repos/bypasslane/android-customer-display/stargazers","contributors_url":"https://api.github.com/repos/bypasslane/android-customer-display/contributors","subscribers_url":"https://api.github.com/repos/bypasslane/android-customer-display/subscribers","subscription_url":"https://api.github.com/repos/bypasslane/android-customer-display/subscription","commits_url":"https://api.github.com/repos/bypasslane/android-customer-display/commits{/sha}","git_commits_url":"https://api.github.com/repos/bypasslane/android-customer-display/git/commits{/sha}","comments_url":"https://api.github.com/repos/bypasslane/android-customer-display/comments{/number}","issue_comment_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues/comments{/number}","contents_url":"https://api.github.com/repos/bypasslane/android-customer-display/contents/{+path}","compare_url":"https://api.github.com/repos/bypasslane/android-customer-display/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bypasslane/android-customer-display/merges","archive_url":"https://api.github.com/repos/bypasslane/android-customer-display/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bypasslane/android-customer-display/downloads","issues_url":"https://api.github.com/repos/bypasslane/android-customer-display/issues{/number}","pulls_url":"https://api.github.com/repos/bypasslane/android-customer-display/pulls{/number}","milestones_url":"https://api.github.com/repos/bypasslane/android-customer-display/milestones{/number}","notifications_url":"https://api.github.com/repos/bypasslane/android-customer-display/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bypasslane/android-customer-display/labels{/name}","releases_url":"https://api.github.com/repos/bypasslane/android-customer-display/releases{/id}","created_at":"2015-12-16T17:50:43Z","updated_at":"2015-12-16T19:34:51Z","pushed_at":"2016-01-12T21:52:46Z","git_url":"git://github.com/bypasslane/android-customer-display.git","ssh_url":"git@github.com:bypasslane/android-customer-display.git","clone_url":"https://github.com/bypasslane/android-customer-display.git","svn_url":"https://github.com/bypasslane/android-customer-display","homepage":null,"size":148,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1"},"html":{"href":"https://github.com/bypasslane/android-customer-display/pull/1"},"issue":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/issues/1"},"comments":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/bypasslane/android-customer-display/statuses/7bda0fed2612be5f73dee804bac4603d9273f787"}}}}