Skip to content
This repository was archived by the owner on Apr 1, 2022. It is now read-only.
Ken Hoover edited this page Oct 13, 2019 · 3 revisions

How the current (Sept. 2019) setup works

The soda machine's controller for dispensing drinks and sending faceplate button presses is attached to a P115e board via MDB (the controller is master), which communicates with vdb_server. vdb_server is acting as a credit card reader, and forwards the final two bytes of the product id to soda_server, which responds whether a soda should be dispensed or not.

The bill and coin acceptors are attached to the P115 via MDB (the P115 is master), and the P115 is set to event mode. It will poll the two acceptors every XXX milliseconds, and notify the mdb_server whenever an event happens. mdb_server will tell soda_server the exact string it received, at which point soda_server will do whatever the event corresponds to. If a bill is escrowed, soda_server will tell mdb_server to either deposit the bill or reject it (via sending the corresponding P115 command string).

How the new setup could work

(Treat this as a design doc? Or would an overleaf or G-doc be a better place for that?)

qibixx config

Have this set up with the master and cashless slave drivers enabled, cashless works with vdb_server and master with mdb_server as before.

vdb_server

Assuming the cashless driver, has exactly three functions:

  • initialize the driver settings;
  • forward soda choices to soda_server, and;
  • tell the soda machine controller to dispense or not based on the response to the above.

API

To soda_server

  • send_selection(soda_id): tells soda_server someone pressed one of the front soda buttons.
    • Response: dispense or not.
  • notify_dispense(soda_id): tells soda_server a soda was successfully dispensed.

Something that should be tracked over a whole send_selection->response->notify_dispense chain is the user ID, to avoid any edge cases involving logging out mid-dispense. Could also make the dispense command something soda_server requests, and have it hold on to the current user until the response is received and handled.

Alternative

We could just roll the entire functionality of vdb_server into soda_server; once you have the qibixx handling the low level MDB stuff, there's not really much that the server needs to do, other than constantly polling the USB interface.

mdb_server

This now has to handle polling all the peripherals, initializing them, and overall implementing the controller end of the MDB protocol. It also has to forward information about deposits to soda_server, as well as enable and disable accepting bills and coins.

API

To soda_server

  • notify_coin_deposit(amount): tells soda_server that coins have been deposited.
  • (Optional) notify_cash_rejected(): tells soda_server that someone tried to deposit money and the automatic verifiers rejected it.
  • bill_escrowed(): tells soda_server that a bill's been put in escrow.
    • Response: cash or reject
  • notify_bill_deposit(amount): tells soda_server that cash has been deposited.
  • notify_logout(): tells soda_server someone pushed the logout button.

Again, for the whole bill_escrowed->response->notify_bill_deposit flow, the user id needs to be held on to, with maybe a similar reversal of soda_server commanding mdb_server to deposit as suggested for vending. Also can't allow enabling/disabling in the middle of that.

From soda_server

  • enable(): enable accepting cash.
  • disable(): disable accepting cash.

Resources

  • MDB specification
  • P115 specification
  • P115e specification
  • qibixx MDB specification
  • qibixx online docs (This is probably the more useful of the two, and we should update the qibixx to the latest firmware. It would vastly simplify vdb_server to use the built-in cashless driver that the current firmware version seems to have.)
  • PyUSB, a library similar to libusb implemented in pure Python. If the qibixx is only showing one tty endpoint now, could use this to split the device into two streams (assuming that it's not even simpler and can be done by just testing the first character on reads).