static void RespondToBleDataRequestWithErrors(SerialBeacon beacon, Dictionary <string, object> requestInfo, List <byte> errors) { requestInfo[Constants.WALLET_ERRORS_TINY_KEY] = errors; var responseData = DictionarySerializer.SerializeToByteArray(requestInfo); beacon.RespondToBleDataRequest(responseData); }
static void RespondToBleDataRequest(SerialBeacon beacon, byte[] requestData) { try { var requestInfo = DictionarySerializer.DeserializeFromByteArray(requestData); if (requestInfo != null) { var dataTypeString = (string)requestInfo[Constants.WALLET_DATA_TYPE_TINY_KEY]; if (!string.IsNullOrEmpty(dataTypeString)) { Console.WriteLine("Received data request {0}.", JsonConvert.SerializeObject(requestInfo)); if (string.Compare(dataTypeString, ((byte)eWalletDataTypes.CardBalanceRequest).ToString(), true) == 0) { RespondToCardBalanceRequest(beacon, requestInfo); } else if (string.Compare(dataTypeString, ((byte)eWalletDataTypes.CardRedmeptionRequest).ToString(), true) == 0) { RespondToCardRedemptionRequest(beacon, requestInfo); } else { Console.WriteLine("BLE data request type {0} not supported.", dataTypeString); RespondToBleDataRequestWithErrors(beacon, requestInfo, new List <byte> { (byte)eWalletErrors.RequestTypeNotSupported }); } } else { Console.WriteLine("BLE data request JSON invalid."); RespondToBleDataRequestWithErrors(beacon, requestInfo, new List <byte> { (byte)eWalletErrors.JSONInvalid }); } } else { Console.WriteLine("LE data request type missing."); RespondToBleDataRequestWithErrors(beacon, requestInfo, new List <byte> { (byte)eWalletErrors.RequestTypeMissing }); } } catch (Exception ex) { Debug.Print("Exception in RespondToBleDataRequest: {0}", ex.GetBaseException().Message); } }
static void RespondToCardRedemptionRequest(SerialBeacon beacon, Dictionary <string, object> requestInfo) { var barcode = (string)requestInfo[Constants.WALLET_CARD_BARCODE_TINY_KEY]; var merchantID = (string)requestInfo[Constants.WALLET_MERCHANT_ID_TINY_KEY]; var transactionID = (string)requestInfo[Constants.WALLET_TRANSACTION_ID_TINY_KEY]; var deviceID = (string)requestInfo[Constants.WALLET_DEVICE_ID_TINY_KEY]; decimal?amount = null; if (requestInfo.ContainsKey(Constants.WALLET_AMOUNT_TINY_KEY)) { var amountString = (string)requestInfo[Constants.WALLET_AMOUNT_TINY_KEY]; if (!String.IsNullOrEmpty(amountString)) { amount = decimal.Parse(amountString); } } var errors = new List <byte>(); if (string.IsNullOrEmpty(barcode)) { Console.WriteLine("Barcode missing."); errors.Add((byte)eWalletErrors.CardBarcodeMissing); } if (string.IsNullOrEmpty(merchantID)) { Console.WriteLine("Merchant ID missing."); errors.Add((byte)eWalletErrors.MerchantIDMissing); } if (string.IsNullOrEmpty(transactionID)) { Console.WriteLine("Transaction ID missing."); errors.Add((byte)eWalletErrors.TransactionIDMissing); } if (errors.Count > 0) { RespondToBleDataRequestWithErrors(beacon, requestInfo, errors); return; } var transaction = _demoDataSource.GetTransaction(transactionID); if (transaction == null) { Console.WriteLine("Transaction {0} not found.", transactionID); errors.Add((byte)eWalletErrors.TransactionNotFound); } else if (transaction.IsCanceled) { Console.WriteLine("Transaction {0} was previously canceled at {1}.", transactionID, transaction.CanceledAt); errors.Add((byte)eWalletErrors.TransactionCanceled); } else if (transaction.IsComplete) { Console.WriteLine("Transaction {0} completed.", transactionID); errors.Add((byte)eWalletErrors.TransactionCompleted); } else if (amount.HasValue && Decimal.Compare(amount.Value, transaction.RemainingAmount) > 0) { Console.WriteLine("Amount {0:0.00} exceeds remaining amount {1:0.00} on transaction {2}.", amount.Value, transaction.RemainingAmount, transactionID); errors.Add((byte)eWalletErrors.SpecifiedAmountExceedsRemainingAmount); } var card = _demoDataSource.GetCard(merchantID, barcode); if (card == null) { Console.WriteLine("Card {0} for merchant {1} not found.", barcode, merchantID); errors.Add((byte)eWalletErrors.CardNotFound); } else if (amount.HasValue && Decimal.Compare(amount.Value, card.CurrentBalance) > 0) { Console.WriteLine("Card {0} balance {1:0.00} less than amount {2:0.00} specified.", barcode, card.CurrentBalance, amount.Value); errors.Add((byte)eWalletErrors.CardBalanceInsufficient); } if (errors.Count > 0) { RespondToBleDataRequestWithErrors(beacon, requestInfo, errors); return; } var item = new TenderLineItem { Card = card, DeviceID = deviceID, }; transaction.AddTenderLineItem(item); if (amount.HasValue) { item.Amount = amount.Value; card.CurrentBalance = card.CurrentBalance - amount.Value; transaction.RemainingAmount = transaction.RemainingAmount - amount.Value; } else if (Decimal.Compare(transaction.RemainingAmount, card.CurrentBalance) >= 0) { item.Amount = card.CurrentBalance; transaction.RemainingAmount = transaction.RemainingAmount - card.CurrentBalance; card.CurrentBalance = 0.00M; } else { item.Amount = transaction.RemainingAmount; card.CurrentBalance = card.CurrentBalance - transaction.RemainingAmount; transaction.RemainingAmount = 0.00M; } var responseInfo = new Dictionary <string, object>(requestInfo); responseInfo[Constants.WALLET_CARD_CURRENT_BALANCE_TINY_KEY] = card.CurrentBalance.ToString("0.00"); responseInfo[Constants.WALLET_TRANSACTION_REMAINING_AMOUNT_TINY_KEY] = transaction.RemainingAmount.ToString("0.00"); var responseData = DictionarySerializer.SerializeToByteArray(responseInfo); if (responseData != null) { try { Console.WriteLine("Canceling data blocks."); beacon.CancelDataBlocks(); Console.WriteLine("Data request response: {0}.", JsonConvert.SerializeObject(responseInfo)); beacon.RespondToBleDataRequest(responseData); if (Decimal.Compare(transaction.RemainingAmount, 0.0M) > 0) { TenderCard(transaction); } } catch { } } else { Console.WriteLine("Serialization failed for card redemption request response."); RespondToBleDataRequestWithErrors(beacon, requestInfo, new List <byte> { (byte)eWalletErrors.SerializationFailed }); } }
static void RespondToCardBalanceRequest(SerialBeacon beacon, Dictionary <string, object> requestInfo) { var barcode = (string)requestInfo[Constants.WALLET_CARD_BARCODE_TINY_KEY]; var merchantID = (string)requestInfo[Constants.WALLET_MERCHANT_ID_TINY_KEY]; var errors = new List <byte>(); if (string.IsNullOrEmpty(barcode)) { Console.WriteLine("Barcode missing."); errors.Add((byte)eWalletErrors.CardBarcodeMissing); } if (string.IsNullOrEmpty(merchantID)) { Console.WriteLine("Merchant ID missing."); errors.Add((byte)eWalletErrors.MerchantIDMissing); } if (errors.Count > 0) { RespondToBleDataRequestWithErrors(beacon, requestInfo, errors); return; } var card = _demoDataSource.GetCard(merchantID, barcode); if (card == null) { Console.WriteLine("Card {0} for merchant {1} not found.", barcode, merchantID); RespondToBleDataRequestWithErrors(beacon, requestInfo, new List <byte> { (byte)eWalletErrors.CardNotFound }); return; } var responseInfo = new Dictionary <string, object>(requestInfo); responseInfo[Constants.WALLET_CARD_CURRENT_BALANCE_TINY_KEY] = card.CurrentBalance.ToString("0.00"); var responseData = DictionarySerializer.SerializeToByteArray(responseInfo); if (responseData != null) { Console.WriteLine("Data request response: {0}.", JsonConvert.SerializeObject(responseInfo)); try { beacon.RespondToBleDataRequest(responseData); } catch (Exception ex) { Debug.Print("Failure when calling beacon.RespondToBleDataRequest(responseData) in Program: {0}", ex.GetBaseException().Message); } } else { Console.WriteLine("Serialization failed for card balance request response."); RespondToBleDataRequestWithErrors(beacon, requestInfo, new List <byte> { (byte)eWalletErrors.SerializationFailed }); } }
static void Main(string[] args) { if (args.Contains("--debug")) { SerialBeaconManager.SpoolDebugOutputToConsole(); } Console.WriteLine("BlueCats Wallet Version {0}", _version); Console.WriteLine(); // Discover serial beacons Console.WriteLine("Discovering connected beacons..."); var availableBeacons = SerialBeaconManager.DiscoverSerialBeacons(); while (!availableBeacons.Any()) { Console.WriteLine("No beacons detected. Connect a beacon and press enter."); Console.ReadKey(); Console.WriteLine("Rescanning for connected serial beacons..."); availableBeacons = SerialBeaconManager.DiscoverSerialBeacons(); } // Select a beacon if (availableBeacons.Count == 1) { _selectedBeacon = availableBeacons.First(); } else { while (_selectedBeacon == null) { for (var i = 0; i < availableBeacons.Count; i++) { Console.WriteLine("{0}) {1}", i + 1, availableBeacons[i]); } Console.WriteLine(); try { var choice = Convert.ToInt32(GetUserInput("Select a beacon")) - 1; _selectedBeacon = availableBeacons.ElementAt(choice); } catch { Console.WriteLine("Invalid choice, enter a beacon number."); } } Console.WriteLine(); } // Attach to beacon and start listening try { _selectedBeacon.Attach(); _selectedBeacon.BleConnectedEvent += _selectedBeacon_BleConnectedEvent; _selectedBeacon.BleDisconnectedEvent += _selectedBeacon_BleDisconnectedEvent; _selectedBeacon.BleDataRequestEvent += _selectedBeacon_BleDataRequestEvent; _selectedBeacon.BleDataBlocksSentEvent += _selectedBeacon_BleDataBlocksSentEvent; _selectedBeacon.BleDataIndicatedEvent += _selectedBeacon_BleDataIndicatedEvent; try { _selectedBeacon.WriteEventsEnabled(true); } catch (Exception ex) { // enable events not supported in older beacon fw Debug.Print("* Error on command WriteEventsEnabled(true): {0}", ex.GetBaseException().Message, null); } Console.WriteLine("Attached to {0}", _selectedBeacon); } catch { if (_selectedBeacon.IsAttached) { _selectedBeacon.Detach(); } Console.WriteLine("Failed to attach {0}", _selectedBeacon); } Console.WriteLine(); // Display merchant info var merchantForMerchantId = Merchant.GenerateDemoMerchants(5); var merchants = merchantForMerchantId.Values.ToList(); var cards = Card.GenerateDemoCards(merchants); _demoDataSource = new DemoDataSource(merchantForMerchantId, cards); Console.WriteLine(_demoDataSource.ToString()); // Display command prompt Console.WriteLine("Enter 'commands' to see a list of commands."); Console.WriteLine(); var quit = false; while (!quit) { var line = GetUserInput(">"); if (line == null) { continue; } var parts = line.Split(' '); if (parts.Length > 0) { quit = RunWalletCommand(parts); } } // Cleanup _selectedBeacon.BleConnectedEvent -= _selectedBeacon_BleConnectedEvent; _selectedBeacon.BleDisconnectedEvent -= _selectedBeacon_BleDisconnectedEvent; _selectedBeacon.BleDataRequestEvent -= _selectedBeacon_BleDataRequestEvent; _selectedBeacon.BleDataBlocksSentEvent -= _selectedBeacon_BleDataBlocksSentEvent; _selectedBeacon.BleDataIndicatedEvent -= _selectedBeacon_BleDataIndicatedEvent; if (_selectedBeacon.IsAttached) { _selectedBeacon.Detach(); } }