how to get all (error) messages from between B2B banknote and paylink

Support for the Milan Intelligent interface, sold by Money Controls as the Paylink USB unit and for the earlier PCI card version.

Moderators: aardvark, davebush, Admin

davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

Hi,

I think this works reliably:

Code: Select all

#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include "..\..\AESImhei.h"


void SendCommand(char* Line) ;

main()
    {
    long OpenStatus = OpenMHE() ;
    if (OpenStatus != 0)
        {
        printf("IMHEI open failed - %ld\n", OpenStatus) ;
        return 0 ;
        }
    EnableInterface() ;
    SendCommand("d ccn") ;
    }


void SendCommand(char* Line)
    {
    struct
        {
        long Code ;
        long Length ;
        char Data[128] ;
        } Block ;
    Block.Code = 0 ;
    strcpy(Block.Data, Line) ;
    Block.Length = strlen(Block.Data) + 1 ;        // include NULL
    WriteInterfaceBlock(-1, (char*)&Block, 8 + Block.Length) ;

    char Reply[128] ;
    while (ReadInterfaceBlock(-1, Reply, 128) == 0)
       {
       Sleep(1) ;
       }
   }
Regards

Dave
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

Hi Dave,

Sorry about that.
We are using C# and Python as major development language.
Is it also possible to have sample code of applying "d ccn" from you?

Thank you so much for always great help to us!!

David
davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

The only bit that I think is different across the languages, is the construction of the block of memory.

I am not a C# programmer, but I beleive this will give you waht you want:

Code: Select all

byte[136] Block ;

Block[0] = 0 ;
Block[1] = 0 ;
Block[2] = 0 ;
Block[3] = 0 ;
Block[4] = 6 ;
Block[5] = 0 ;
Block[6] = 0 ;
Block[7] = 0 ;
Block[8] = 'd' ;
Block[9] = ' ' ;
Block[10] = 'c' ;
Block[11] = 'c' ;
Block[12] = 'n' ;
Block[13] = 0 ;

WriteInterfaceBlock(-1, Block, 14) ;
Regards

Dave
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

Hi Dave,

Thank you for the info.

David
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

hi Dave,

From paylink.log, we could find some error message as below.
May I have your help to check and see how to get those error messages when implementing SW integration?

.
.
.
07:40:42.358 00:17
07:41:05.314 CCNet: Status 47
07:41:05.314 CCNet: Unit Fault ed
.
.
.

Thank you in advance.

David
davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

Hi,

Status 47 is a generic fault status, the additional information is the hex value ed.

This is reported to the application on the NextEvent() channel as a "Reported Fault" with the RawEvent field set to 0xed.

Regards

Dave
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

Hi Dave,

We are trying to handle the process once paper jam appear
However, we found that , after long waiting, paylink.exe get crashed.
We checked the paylink.log and see CCNet returning the error code, however, Paylink didn't show any error message.
Would you please advise any?

David
davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

Hi,

Paylink.exe should never crash, can you give me more details.

If you want me to give any advice on your problem, you'll have to post the Paylink log from a short time before the problem to the end.

Regards

Dave
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

hi Dave,

Please refer to the below link for downloading paylink.log.
https://drive.google.com/file/d/19t_6iw ... sp=sharing

Line 1198209 => the first time of CCNet response to error [e6]
then CCNET keeps receiving error message : [e6],
But, paylink log doesn't show any error message...only CCNet does.

until Line 1287808, paylink.exe crashed...

Additional info for you, we are using AesImhei64.Net.dll to retrieve the paylink info/response for SW integration.


David
davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

Hi,

If you look carefully at log there:

Code: Select all

11:57:06.100 CCNet:  ==   3:  8  <  [02] [01] [08] [42] [00] [00] [04] [55]
11:57:06.100 CCNet:  ==   3: ACK
>  [02] [01] [06] [33] [62] [34]
11:57:37.805 CCNet:  ==   3:  8  <  [02] [01] [08] [47] [e6] [00] [f0] [d1]
11:57:37.805 CCNet:  ==   3: ACK
You'll see the time jump from 11:57:06 up to 11:57:37 - for some reason the logging system can't keep and has lost 30 seconds worth of log. The notification of E6 would be in this misssing section.

Looking further back in the log, I see:

Code: Select all

11:39:07.540 CCNet:  ==   3:  8  <  [02] [01] [08] [47] [ed] [00] [58] [35]
11:39:07.563 CCNet:  ==   3: ACK
11:39:07.563 CCNet: Status 47
11:39:07.563 CCNet: Unit Fault ed
11:39:07.563 DP: Lost fault 01ed0121
The final line in this excerpt is showing that for some reason your application is not unloading the event queue, and so the fault events are being discarded. I stongly suspect that trhis also happened during the missing 30 seconds

Regards

Dave
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

hi Dave,

2 questions...

1. What do you mean about "unloading the event queue"?
or could you please show me the related pages in MilanPaylinkProgrammersManual for further information?
Then, I could read the info for further code development.

2. Regarding logging system, do you advise what we should do for not losing logs?
davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

1/ You should be picking up the errors from the Paylink error queue, as explained earlier in this thread.
For instance in the log you see:

Code: Select all

11:39:07.563 CCNet: Status 47
11:39:07.563 CCNet: Unit Fault ed
11:39:07.563 DP: Lost fault 01ed0121
In this case, status 47 is a generic fault status, the additional information is the hex value ed. Paylink packages this up into an event and tries to add it the queue. The queue is read by the application on the NextEvent() channel as a "Reported Fault" with the RawEvent field set to 0xed. In this case the queue is full, so the event is discarded.

If your Application calls NextEvent(EventBlock), it should see an event block with the values:
EventBlock.EventCode = IMHEI_NOTE_UNIT_REPORTED_FAULT
EventBlock.RawEvent = 0xed
EventBlock.DisplenserEvent = false

The details on the API are on page 71 onwards of MilanPaylinkProgrammersManual.pdf, some details on the CCNet usage are on page 52 of MilanPaylinkSystemManual.pdf


2/ The Paylink log is just not designed to handle this volume of data continuously. There is nothing you can do.

Regards

Dave
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

Hi Dave,

actually, we are thinking how to get the error code from Paylink once the paper-jammed or coin-jammed event pops up.
Then, we can take use of error code to show on the panel, and then suggest the operator taking the simple steps to clear the banknote recycler's fault.

Now, we are trying to retrieve error code via "NextEventQueue",
The way that we are doing now is to monitor "IMHEI_NOTE_UNIT_REPORTED_FAULT", but we didn't see this change when paylink.log have showed unit fault.

Is it possible to share me some demo code how to implement between "payout" and "NextEventQueue"?

Or, how could I know there is a new event coming up with error code?

Please kindly advise any...

David
davebush
Posts: 482
Joined: Fri Oct 22, 2004 12:20 pm

Re: how to get all (error) messages from between B2B banknote and paylink

Post by davebush »

Hi,

I strongly recommend that you run the Demo program in a test lab, and observe the events being reported by that. (They appear in a drop down list in the centre of the dialog)

There is C# code to do this in SDK\Examples\C #\Full C#Demo\C#Demo\MainForm.cs, in the method UpdateEventControls()

Regards

Dave

Code: Select all

	AESImhei.EventDetailBlock eventBlock = new AESImhei.EventDetailBlock();
	int eventCode = AESImhei.NextEvent(eventBlock) ;
        while (eventCode != AESImhei.IMHEI_NULL)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                switch (eventCode)
                {
                    case AESImhei.IMHEI_APPLICATION_START:
                        sb.Append("Application Start");
                        break;
                    case AESImhei.IMHEI_APPLICATION_EXIT:
                        sb.Append("Application Exit");
                        break;
                    case AESImhei.IMHEI_INTERFACE_START:
                        sb.Append("Interface Start");
                        break;
                    case AESImhei.IMHEI_OVERFLOW:
                        sb.Append("Overflow");
                        break;
                    case AESImhei.IMHEI_NULL:
                        sb.Append("Null");
                        break;
                }
                if (sb.Length == 0)
                {
                    // add the unit type
                    switch ((ushort)eventCode & AESImhei.UNIT_TYPE_MASK)
                    {
                        case AESImhei.COIN_DISPENSER_EVENT:
                            sb.Append("Coin Dispenser: ");
                            break;
                        case AESImhei.NOTE_DISPENSER_EVENT:
                            sb.Append("Note Dispenser: ");
                            break;
                        case AESImhei.COIN_EVENT:
                            sb.Append("Coin Acceptor: ");
                            break;
                        case AESImhei.NOTE_EVENT:
                            sb.Append("Note Acceptor: ");
                            break;
                        default:
                            sb.Append("Device: ");
                            break;
                    }

                    // add the fault or event depending on the fault bit
                    if (((ushort)eventCode & AESImhei.FAULT_BIT) > 0)
                    {
                        switch ((ushort)eventCode & AESImhei.EVENT_CODE_MASK)
                        {
                            case AESImhei.NOW_OK:
                                sb.Append("Now OK");
                                break;
                            case AESImhei.REPORTED_FAULT:
                                sb.Append("Unit Reported Fault");
                                break;
                            case AESImhei.UNIT_TIMEOUT:
                                sb.Append("Unit Timeout");
                                break;
                            case AESImhei.UNIT_RESET:
                                sb.Append("Unit Reset");
                                break;
                            case AESImhei.SELF_TEST_REFUSED:
                                sb.Append("Self Test refused");
                                break;
                            default:
                                sb.Append("Fault");
                                break;                        }
                    }
                    else
                    {
                        switch ((ushort)eventCode & AESImhei.EVENT_CODE_MASK)
                        {
                            case AESImhei.EVENT_OK:
                                sb.Append("OK");
                                break;
                            case AESImhei.EVENT_BUSY:
                                sb.Append("Busy");
                                break;
                            case AESImhei.REJECTED:
                                sb.Append("Rejected");
                                break;
                            case AESImhei.INHIBITED:
                                sb.Append("Inhibited");
                                break;
                            case AESImhei.MISREAD:
                                sb.Append("Misread");
                                break;
                            case AESImhei.FRAUD:
                                sb.Append("Fraud");
                                break;
                            case AESImhei.JAM:
                                sb.Append("Jam");
                                break;
                            case AESImhei.JAM_FIXED:
                                sb.Append("Jam Fixed");
                                break;
                            case AESImhei.RETURN:
                                sb.Append("Return");
                                break;
                            case AESImhei.OUTPUT_PROBLEM:
                                sb.Append("Output Problem");
                                break;
                            case AESImhei.OUTPUT_FIXED:
                                sb.Append("Output Fixed");
                                break;
                            case AESImhei.INTERNAL_PROBLEM:
                                sb.Append("Internal Problem");
                                break;
                            case AESImhei.UNKNOWN:
                                sb.Append("Unknown");
                                break;
                            case AESImhei.DISPENSE_UPDATE:
                                sb.Append("Dispenser Update");
                                break;
                            default:
                                sb.Append("Event");
                                break;
                        }
                    }
                }

                int len = sb.Length;
                int noSpaces = 50 - len;
                for (int i = 0; i < noSpaces; ++i)
                {
                    sb.Append(" ");
                }
                sb.AppendFormat("| Raw Code: {0:x4}  Disp: {1}", eventBlock.RawEvent, eventBlock.DispenserEvent);

                this.EventListBox.Items.Add(sb.ToString());
                eventCode = AESImhei.NextEvent(eventBlock);
            }
Aardvark software developer. Please put all communication on the problem through the board for the benefit of others.
flyelephantw
Posts: 25
Joined: Fri Nov 06, 2020 10:49 am

Re: how to get all (error) messages from between B2B banknote and paylink

Post by flyelephantw »

hi Dave,

Thank you so much for the demo code.
1.
In fact, we prefer not to keep polling and deciphering NextEvent,
If these is something wrong(ex.papaer jam) during payout process,
Is there another way to know right away when the event is just updated.


2. Another question is....
we usually use "ReadDispenserDetails" to check the status after calling "payout"
but we can't see any error message or status change when the dispenser is jammed,
would you kindly explain the reason for me?

3. One more question...
What if we are not unloading NextEvent queue? Any side-effect?

David
Post Reply