/// <summary> /// Notify subsriber that data is available for debugging /// </summary> /// <param name="entry"></param> internal virtual void NotifySerialData(DebugBufferEntry entry) { EventHandler <DebugEntryArgs> handler = OnSerialData; if (handler != null) { handler(this, new DebugEntryArgs(entry)); } }
/// <summary> /// Connect to the device and begin speaking rs232 /// </summary> public void Connect() { // Lock so we only have one connection attempt at a time. This protects // from client code behaving badly. lock (_mutex) { try { _port = Config.GetCommPort(); } catch (IOException) { NotifyError(Errors.FailedToOpenPort); return; } _port.ReadTimeout = 500; DebugBufferEntry.SetEpoch(); try { _port.Connect(); // Only start if we connect without error StartRS232Loop(); IsPaused = false; } catch (Exception e) { Log.ErrorFormat("Exception Connecting to acceptor: {0}", e.Message, e); if (OnError != null) { NotifyError(Errors.PortError); } } } }
/// <summary> /// DebugEntry argument describes a debug event /// </summary> /// <param name="entry">DebugBufferEntry describing serial data tx/rx</param> public DebugEntryArgs(DebugBufferEntry entry) { Entry = entry; }
/// <summary> /// The main parsing routine /// </summary> private void ReadAcceptorResp() { var data = PreviouslySentMasterMsg ?? GenerateNormalMessage(); // Attempt to write data to slave NotifySerialData(DebugBufferEntry.AsMaster(data)); WriteWrapper(data); // Blocks until all 11 bytes are read or we give up var resp = ReadWrapper(); // Extract only the states and events NotifySerialData(DebugBufferEntry.AsSlave(resp)); // No data was read, return!! if (resp.Length == 0) { // Do no toggle the ack return; } // Check that we have the same ACK # if (IsBadAckNumber(resp, data)) { PreviouslySentMasterMsg = data; return; } if (IsBadSlaveChecksumOk(resp)) { PreviouslySentMasterMsg = data; return; } // Otherwise we're all good - toggle ack and clear last sent message PreviouslySentMasterMsg = null; Ack ^= 1; // At this point we have sent our message and received a valid response. // Parse the response and act on any state or events that are reported. // Translate raw bytes into friendly enums var slaveMessage = SlaveCodex.ToSlaveMessage(resp); PreviousState = SlaveCodex.GetState(slaveMessage); // Raise a state changed notice for clients NotifyStateChange(PreviousState); // Multiple event may be reported at once var currentEvents = SlaveCodex.GetEvents(slaveMessage); foreach (Events e in Enum.GetValues(typeof(Events))) { // If flag is set in slave message, report event if ((currentEvents & e) == e) { NotifyEvent(e); } } // Check for cassette missing - reports every time cashbox is missing if (!SlaveCodex.IsCashboxPresent(slaveMessage)) { CashboxPresent = false; NotifyError(Errors.CashboxMissing); } // Only report the cashbox attached 1 time after it is re-attached else if (!CashboxPresent) { CashboxPresent = true; SafeEvent(OnCashboxAttached); } // Mask away rest of message to see if a note is in escrow. If this is the first // escrow message, start the escrow timeout clock if (!NoteIsEscrowed && PreviousState == States.Escrowed) { _escrowStart = DateTime.MinValue; } NoteIsEscrowed = PreviousState == States.Escrowed; // Credit bits are 3-5 of data byte 3 var value = SlaveCodex.GetCredit(slaveMessage); if (value > 0) { Credit = (byte)value; } // Per the spec, credit message is issued by master after stack event is // sent by the slave. If the previous event was stacked or returned, we // must clear the escrow command to completely release the note from // escrow state. // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault switch (PreviousEvents) { case Events.Stacked: NotifyCredit(Credit); // C# does not allow fallthrough so we will goto :) goto case Events.Returned; case Events.Returned: // Clear our the pending escrow command once we've stacked or returned the note EscrowCommand = EscrowCommands.None; Credit = 0; break; } // Update the events aster the check for check so as to not lose a credit message PreviousEvents = currentEvents; }
/// <summary> /// Notify subsriber that data is available for debugging /// </summary> /// <param name="entry"></param> internal virtual void NotifySerialData(DebugBufferEntry entry) { EventHandler<DebugEntryArgs> handler = OnSerialData; if (handler != null) { handler(this, new DebugEntryArgs(entry)); } }
/// <summary> /// Notify subsriber that data is available for debugging /// </summary> /// <param name="entry"></param> internal virtual void NotifySerialData(DebugBufferEntry entry) { var handler = OnSerialData; handler?.Invoke(this, new DebugEntryArgs(entry)); }