A C++11 application that mimics the functionality of a coffee vending machine. Provides the means of ordering one or more customizable cups of coffee, providing payment, receiving change, and dispensing the correct product.
- Compiles on build.particle.io (you will need to create a free account to make this work). Note that you DO NOT need to buy a Particle device as part of this exercise - the goal is to write a firmware application against the Particle Cloud and Firmware APIs as documented).
- Note: we are not asking you to purchase a Particle device to actually run this code.
- Serial communications will be sent & received via Serial device using Opti Vending Machine Message Protocol defined below.
- Does not depend on any external web services.
- Does not require any persistent data storage.
- Only manages 1 coffee order at once. One order may consist of multiple coffees of different sizes. You can assume whatever physical apparatus is connected to the other end of this service prevents more than 1 user from using it at once.
The following is a list of APIs we anticipate you will need to implement your solution.
- digitalread() to read value of a button's pin
- millis() to measure time
- Serial
- Serial.begin(9600) to setup serial connection
- Serial.available() and Serial.read() to read incoming messages
- Serial.write() to write messages
- Order coffee in 3 sizes (small for $1.75, medium for $2.00, large for $2.25).
- Allow multiple coffee orders per payment transaction, up to 5 coffees.
- Allow adding money in standard monetary increments only (from $0.05 to $20).
- Allow user to specify the end of a payment transaction and "Dispense" coffee and change.
- “Dispense” coffee when an order is completed if adequate payment has been provided and display money remaining in payment transaction. The developer can assume that the physical implications of this dispense operation always succeed and do not need to be verified - in this context, "dispense" means complete the order.
- Insertion of money is communicated to device by serial message
- Device sends updates to user via events sent via Serial communications
- At start up, wait for message of the day template and then display message of the day on LCD
- Small Button is GPIO PIN A0
- Medium Button is GPIO PIN A1
- Large Button is GPI0 PIN A2
- Dispense/Cancel Button GPIO Pin A3
- Dispense will be triggered by press & release
- Cancel will be triggered by press & hold > 2 seconds
- Initialized state values (before messages arrive by Serial):
msgDay = '' //empty ASCII stringorder = {0x0, 0x0, 0x0} // zero small, zero medium, zero large coffeescurFunds = 0 //zero cents
- Message of the day value is written to LCD by sending
setLCDmessage.- The ASCII string to send with
setLCDwill be evaluated using last receivedmsgOfDaytemplate value and replacing each occurrence of%KEY%with the corresponding value for thatKEY. - Each
%KEY%will be matched and replaced left to right - If
KEYis an unknown key, then it will not be replaced. - Known Keys and corresponding value to render (as base 10 string)
smallCount: the count of small coffees in ordermediumCount: the count of medium coffees in orderlargeCount: the count of large coffees in ordercurFunds: the accumulated money inserted (simply a base 10 string of cents accumulated)
- Example:
Order: %smallCount%S %mediumCount%M %largeCount%L, Funds: %curFunds%.- If
smallCount,mediumCount,largeCountandcurFundsare1,2,3and625respectively, then the expected output isOrder: 1S 2M 3L, Funds: 625. Note:curFundsin this examples is less than funds required for order.
- If
- The ASCII string to send with
- When money is added,
- first display human readable message of added value and accumulated
curFundson LCD usingsetLCD - then send message for
curFunds
- first display human readable message of added value and accumulated
- When coffee is added
- first display human readable message on LCD showing the 3 sizes of coffee and their counts using
setLCD - then send message for
order
- first display human readable message on LCD showing the 3 sizes of coffee and their counts using
- When dispense is triggered and there are insufficient funds:
- first display human readable insufficient funds message on LCD
- then send message for
insFunds
- When dispense is triggered and there are sufficient funds:
- first display human readable receipt message on LCD by sending
setLCDmessage - then send messages for
receipt,order,refund(in this order) - then reset state for
curFundsandorder - then send messages for
curFundsandorder(in this order) - then wait 3 seconds
- then reset LCD with message of the day (using current
msgOfDaytemplate)
- first display human readable receipt message on LCD by sending
- When cancel is triggered:
- first display human readable refund message on LCD by sending
setLCDmessage - then send message for
cancelandrefund(in this order) - then reset state for
curFundsandorder - then send messages for
curFundsandorder(in this order) - then wait 3 seconds
- then reset LCD with message of the day (using current
msgOfDaytemplate)
- first display human readable refund message on LCD by sending
uint16_t&uint32_tare little endian in messages sent and received- Assume device hardware is little endian
- Each serial message is 3 fields:
- A
KEYfield of 8 bytes- If
Keyis less than 8 bytes, it will padded with0x0
- If
- A
VALUESIZEfield of 2 bytes (uint16_t) - A
VALUEfield of N bytes where N is the number of bytes defined by valueSize
- A
Messages received by device:
msgOfDay: Specifies the message of the day template. Payload is ASCII string.addValue: Specifies value of money inserted. Payload isuint32_trepresenting value in cents
Messages sent by device:
setLCD: Specifies LCD display message. Payload is ASCII string.curFunds: Specifies the accumulated money inserted. Payload isuint32_trepresenting value in centsorder: Specifies number of small, medium and large coffees respectively. Payload is 3uint32_tvalues in sequence of small, medium and large coffees.insFunds: Sent when dispense is triggered and there is insufficient funds for coffees in order. No payload. (VALUESIZE is 0)receipt: Sent when dispense is triggered and there is sufficient funds for coffees in order. Payload is human readable summary of order. Include coffee counts, subtotals, total, and refund.cancel: Sent when cancel is triggered. No payload. (VALUESIZE is 0)refund: Specifies refund after dispense or cancel is triggered. Payload isuint32_tspecifiying value in cents.