The iPad running VisioLab's Blink app (scanner) runs a websocket server in the local network on ws:/<local-ip>/visiolab-cash-register
.
Each message contains an event
and a data
property at the top level. The event
property identifies the type of the message, so that actions can be dispatched based on it. The data
property contains the actual content of the message. Messages constitute events and there is no fixed request-response relation between them. Still the events are expected to follow a certain sequence as described below.
Once the register has established a connection, it should synchronize its articles using the syncArticles
operation. Afterwards the scanner is ready to detect food.
Once articles are detected and the "Pay" button is pressed to initiate the checkout, setBasket
will be sent. The register can optionally report actual article prices after recalculation based on guest identification using updateBasket
at any time. If scale articles are detected, they are not send in the initial setBasket
event. Instead they are send individually with the weighArticle
command, to which the register should respond with a articleWeighed
event in a case of success or with a weighingFailed
event in a case of failure. The scanner can add additional articles to the basket after weighing using the addArticles
event. The guestAuthenticated
event should be send when a guest is identified, e.g. by putting their card on the reader, to inform the scanner that payment flows that require upfront authentication can proceed.
After all articles are added to the basket, the payment is initiated by sending startPayment
. The register can optionally report actual article prices after recalculation based on guest identification using updateBasket
and should do so before sending articleWeighed
to communicate the total price after weighing. Finally, it should handle the transaction and respond by sending either paymentSuccess
or paymentFailure
.
In case of malformed messages or other errors, the register or the scanner can send an error
event. If deprecated events are being received, both sides can send a warining
event.
Messages the client can send.
Accepts one of the following messages:
Synchronize available articles in the cash register.
The synchronized articles are currently used to updated the prices of articles already available in the Blink app, based on matching PLUs.
{
"event": "syncArticles",
"data": {
"articles": [
{
"id": "a",
"name": "Eggs Benedict",
"priceLookup": "1",
"price": 1
},
{
"id": "b",
"name": "Waldorf Salad",
"priceLookup": "2",
"price": 2
},
{
"id": "c",
"name": "Caesar Salad",
"priceLookup": "3",
"price": 3
}
]
}
}
Report a change in article prices in the current basket after guest identification.
The updated prices are used to already show the correct total price to the guest during payment. The event should always be send before articleWeighed
and already include the price of the weighed article.
{
"event": "updateBasket",
"data": {
"articles": [
{
"id": "a",
"name": "Eggs Benedict",
"priceLookup": "1",
"price": 2
},
{
"id": "b",
"name": "Waldorf Salad",
"priceLookup": "2",
"price": 4
},
{
"id": "c",
"name": "Caesar Salad",
"priceLookup": "3",
"price": 6
}
]
}
}
Report that a guest has been authenticated.
Inform the scanner that payment flows that require upfront authentication can proceed.
{
"event": "guestAuthenticated",
"data": {
"identifier": "1234567890"
}
}
Report a previously authenticated guest has been removed again.
Inform the scanner that payment flows that require upfront authentication can no longer proceed.
{
"event": "guestRemoved",
"data": {
"identifier": "1234567890"
}
}
Report the result of a weighing operation.
{
"event": "articleWeighed",
"data": {
"article": {
"id": "ghi",
"name": "Salad bar",
"priceLookup": "123",
"price": 3.75,
"scale": {
"unit": "g",
"weight": 500
}
}
}
}
Report an error during a weighing operation.
{
"event": "weighingFailed",
"data": {
"reason": "unstable",
"message": {
"en": "Weight not stable.",
"de": "Gewicht nicht stabil."
}
}
}
Report the success of a payment.
{
"event": "paymentSuccess",
"data": {
"total": {
"gross": 5.2
}
}
}
Report the failure of a payment.
{
"event": "paymentFailure",
"data": {
"reason": "cancelled",
"message": {
"en": "Please tap your card again.",
"de": "Bitte legen Sie Ihre Karte erneut auf."
}
}
}
Show a dialog that requires user interaction.
The dialog will be rendered based on the data, including all buttons. It will report back the button that was pressed with the action that is attached to the button. The dialog will be closed automatically after a button was pressed. In case a new dialog should be opened, a new message has to be sent. The dialog can only be shown during checkout and not during scanning.
{
"event": "showDialog",
"data": {
"id": "survey",
"title": {
"en": "Survey",
"de": "Umfrage"
},
"body": {
"en": "How satisfied are you with the interface?",
"de": "Wie zufrieden sind Sie mit der Schnittstelle?"
},
"buttons": [
{
"action": "-1",
"label": {
"en": "Not at all",
"de": "Gar nicht"
}
},
{
"action": "+1",
"label": {
"en": "A lot",
"de": "Sehr"
}
}
]
}
}
Close any currently open dialog.
{
"event": "closeDialog",
"data": {
"id": "survey"
}
}
Report an error.
Report an error that occurred either in response to a received event or due to some external factor.
{
"event": "error",
"data": {
"reason": "malformed",
"message": "Event data could not be decoded."
}
}
Report a warning.
Report a warning that occurred either in response to a received event or due to some external factor.
{
"event": "warning",
"data": {
"reason": "deprecated",
"message": "Field totalGross is deprecated, use `total.gross` instead."
}
}
Messages the sever can send.
Accepts one of the following messages:
Set the current basket.
The contents of the basket are completely replaced by the new contents.
{
"event": "setBasket",
"data": {
"checkoutId": "string",
"articles": [
{
"id": "abc",
"name": "Caesar Salad",
"priceLookup": "123"
},
{
"id": "def",
"name": "Beef Stroganoff",
"priceLookup": "456"
}
]
}
}
Add articles to the current basket.
Previous contents of the basket are kept. If no previous basket was open on the cash register side, it should be opened by the message.
{
"event": "addArticles",
"data": {
"checkoutId": "string",
"articles": [
{
"id": "abc",
"name": "Caesar Salad",
"priceLookup": "123"
},
{
"id": "def",
"name": "Beef Stroganoff",
"priceLookup": "456"
}
]
}
}
Initiate a weighing operation for an article.
This event should activate the scale and either way the article if it is already placed on the scale or placed afterwards.
{
"event": "weighArticle",
"data": {
"article": {
"id": "ghi",
"name": "Salad bar",
"price": 0.75,
"priceLookup": "123",
"scale": {
"unit": "100g"
}
}
}
}
Initiate the payment for the current basket.
{
"event": "startPayment",
"data": {
"paymentMethod": "CREDIT_CARD",
"checkoutId": "7KhiQJfcA5pdyzPofILF"
}
}
Print a physical receipt for a checkout.
Prompts the register to print a receipt for the given checkout. If receiptId
is not provided, the register should print the last receipt.
{
"event": "printReceipt",
"data": {
"checkoutId": "7KhiQJfcA5pdyzPofILF",
"receiptId": "32eab9d1-bacb-4363-a88b-bcd9315ae897"
}
}
Report the user's response to a dialog.
Reports the action of the button that was pressed in a dialog. The actions corresponds to what was set in the showDialog
message.
{
"event": "userInput",
"data": {
"id": "survey",
"action": "+1"
}
}
Reset the cash register.
Cancel all ongoing transactions and delete all articles from the current basket.
{
"event": "reset"
}
Report an error.
Report an error that occurred either in response to a received event or due to some external factor.
{
"event": "error",
"data": {
"reason": "malformed",
"message": "Event data could not be decoded."
}
}
Report a warning.
Report a warning that occurred either in response to a received event or due to some external factor.
{
"event": "warning",
"data": {
"reason": "deprecated",
"message": "Field totalGross is deprecated, use `total.gross` instead."
}
}
Synchronize available articles in the cash register.
The synchronized articles are currently used to updated the prices of articles already available in the Blink app, based on matching PLUs.
Report a change in article prices in the current basket after guest identification.
The updated prices are used to already show the correct total price to the guest during payment. The event should always be send before articleWeighed
and already include the price of the weighed article.
Set the current basket.
The contents of the basket are completely replaced by the new contents.
Add articles to the current basket.
Previous contents of the basket are kept. If no previous basket was open on the cash register side, it should be opened by the message.
Initiate a weighing operation for an article.
This event should activate the scale and either way the article if it is already placed on the scale or placed afterwards.
Initiate the payment for the current basket.
Print a physical receipt for a checkout.
Prompts the register to print a receipt for the given checkout. If receiptId
is not provided, the register should print the last receipt.
Report an error.
Report an error that occurred either in response to a received event or due to some external factor.
Report a warning.
Report a warning that occurred either in response to a received event or due to some external factor.
Report the result of a weighing operation.
Report an error during a weighing operation.
Report that a guest has been authenticated.
Inform the scanner that payment flows that require upfront authentication can proceed.
Report a previously authenticated guest has been removed again.
Inform the scanner that payment flows that require upfront authentication can no longer proceed.
Report the success of a payment.
Report the failure of a payment.
Reset the cash register.
Cancel all ongoing transactions and delete all articles from the current basket.
Show a dialog that requires user interaction.
The dialog will be rendered based on the data, including all buttons. It will report back the button that was pressed with the action that is attached to the button. The dialog will be closed automatically after a button was pressed. In case a new dialog should be opened, a new message has to be sent. The dialog can only be shown during checkout and not during scanning.
Close any currently open dialog.
Report the user's response to a dialog.
Reports the action of the button that was pressed in a dialog. The actions corresponds to what was set in the showDialog
message.