打开 MS-Cash 抽屉,密码错误?糟糕的代码?

发布于 2024-08-20 21:49:37 字数 1097 浏览 11 评论 0原文

这里的经验令人谦卑,我认为这个会让我出丑,但是......我正在尝试将一个古老的收银机程序转换为.net。征服了其他一切,但我无法打开收银机。它连接到 COM1,您应该向 COM1 发送“触发”文本,这将导致寄存器打开。

这是.net 代码。

    MsgBox("Opening Drawer")

    Dim port As System.IO.Ports.SerialPort
    port = New System.IO.Ports.SerialPort("Com1")

    port.PortName = "COM1"
    port.BaudRate = 9600
    port.Parity = IO.Ports.Parity.None
    port.DataBits = 8
    port.StopBits = IO.Ports.StopBits.One
    'port.Handshake = IO.Ports.Handshake.RequestToSend
    port.RtsEnable = True
    'port.DtrEnable = True
    port.Open()
    If port.IsOpen Then

        'MsgBox("Attempt 1")
        port.Write("@@@@@@@@@@@@@@@@@@@@")
        MsgBox("Signal Sent: " & Chr(65))
    Else
        MsgBox("Port is not open")
    End If

    port.Close()
    MsgBox("Pop, durn it!")

我收到消息框“信号已发送”、“完成弹出抽屉”,

该死的东西,只是不会弹出。这是 MS-钱箱 (EP125KC)。肯定连接到COM1,肯定有电。 Chr(65) 是用于弹出抽屉的旧代码,它可以工作:

Open drawerComPort For Output Access Write As #1
Print #1, Chr$(65); "A";
Close #1

注意:上面的代码工作成功。根本问题是由电源线接反引起的(负极在错误的一侧)。

感谢大家的帮助!

Humbling expierence here and I think this one will make a fool of me, but...I'm trying to convert an ancient cash register program to .net. Conquered everything else, but I can't pop open the cash register. Its connected to COM1, you are supposed to send a "trigger" text down COM1 that will cause the register to open.

Here is the .net code.

    MsgBox("Opening Drawer")

    Dim port As System.IO.Ports.SerialPort
    port = New System.IO.Ports.SerialPort("Com1")

    port.PortName = "COM1"
    port.BaudRate = 9600
    port.Parity = IO.Ports.Parity.None
    port.DataBits = 8
    port.StopBits = IO.Ports.StopBits.One
    'port.Handshake = IO.Ports.Handshake.RequestToSend
    port.RtsEnable = True
    'port.DtrEnable = True
    port.Open()
    If port.IsOpen Then

        'MsgBox("Attempt 1")
        port.Write("@@@@@@@@@@@@@@@@@@@@")
        MsgBox("Signal Sent: " & Chr(65))
    Else
        MsgBox("Port is not open")
    End If

    port.Close()
    MsgBox("Pop, durn it!")

I get msgboxes "Signal Sent", "Done Pop Drawer"

Dang thing, just won't pop. It's an MS-Cash Drawer (EP125KC). Definitely connected to COM1, definitely has power. Chr(65) is the old code used to pop drawer and it works:

Open drawerComPort For Output Access Write As #1
Print #1, Chr$(65); "A";
Close #1

NOTE: The above code worked successfully. The root problem was caused by a reveresed power cord (negative was on the wrong side).

Thanks for all the help guys!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雄赳赳气昂昂 2024-08-27 21:49:37

您已将握手设置为“无”,但现金抽屉可能有自己的想法。还将 DtrEnable 设置为 True。 Chr(65) 是“A”的 ASCII 代码,您的 VB 代码表明真正的命令是“AA”。

手册记录了现金抽屉自动调整其波特率。建议发送至少 20 个 @ 字符。真正的命令是 Ctrl+G (Chr(7))。由于波特率不匹配,“AA”命令以前可能有效。也许。

You've set your handshake to None but the cash drawer probably has its own idea. Also set DtrEnable to True. Chr(65) is the ASCII code for an "A", your VB code suggests the real command is "AA".

The manual documents that the cash drawer auto-tunes its baudrate. It recommends sending at least 20 @ characters. And that the real command is Ctrl+G (Chr(7)). The "AA" command might have worked previously due to a baudrate mismatch. Perhaps.

扬花落满肩 2024-08-27 21:49:37

如果我记得我的非常生锈 BASIC。

Print #1, Chr$(65); "A";

意味着打印到 port1 字符 65 后跟字符串“A”,现在字符 65 是“A”,所以在我看来,您应该将“AA”发送到 port1

port.Write("AA");

或交替发送,

port.Write(new byte[]{65,'A'}, 0, 2);

If I remember my very rusty BASIC.

Print #1, Chr$(65); "A";

means print to port1 the character 65 followed by the string "A", Now the character 65 is 'A', so this looks to me like you should be sending "AA" to port1

port.Write("AA");

or alternately,

port.Write(new byte[]{65,'A'}, 0, 2);
阿楠 2024-08-27 21:49:37

它可能会发送 Unicode 65,即 0065,这不会有好结果。

只是一个想法,你可以尝试发送一个 raw int 吗?

It might be sending Unicode 65, which would be 0065, which would not end well.

Just a thought, can you try sending a raw int?

别在捏我脸啦 2024-08-27 21:49:37

我不使用.net,但是端口是否有缓冲?你需要发送一个flush/fflush()吗?

I dont use .net, but is the port buffered? do you need to send a flush/fflush()?

谁的新欢旧爱 2024-08-27 21:49:37

您确定要发送此代码吗?我一直认为代码以 ESC 为前缀,即 0x1b 十六进制...对于现金抽屉...

"\x1bA"

有趣的是使用了双“A”...哦好吧...:)

编辑: 经过思考,我意识到还有另一种方法可以做到这一点,请继续阅读...
我已经对您的原始 BASIC 代码进行了一些防弹修改...将其保存到 opendrawer.bas

Sub OpenDrawer()
drawerComPort = "COM1"
Open drawerComPort For Output Access Write As #1
REM ADDED ERROR HANDLING
ON ERROR GOTO ErrHandler
Print #1, Chr$(65); "A";
Close #1
print "Drawer Ok"
OpenDrawer_Exit:
On Error Goto 0
Exit Sub
ErrHandler:
print "Oops, Write Failed"
Goto OpenDrawer_Exit
End Sub

REM The Main....
OpenDrawer

下载旧的 QB4.5 MS-Quick Basic 编译器,并将其编译为可执行文件,进入opendrawer.exe,QB4.5 可以在此处< /a>.现在,您有责任确保这一点万无一失,即如果写入 COM1 失败会发生什么,发出一条消息,如我修改的示例基本代码中那样

然后您可以使用 System.Diagnostics.Process 来使用隐藏窗口 shell

    public class TestDrawer
    {
        private StringBuilder sbRedirectedOutput = new StringBuilder();
        public string OutputData
        {
            get { return this.sbRedirectedOutput.ToString(); }
        }
        public void Run()
        {
            System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo();
            ps.FileName = "opendrawer";
            ps.ErrorDialog = false;
            ps.CreateNoWindow = true;
            ps.UseShellExecute = false;
            ps.RedirectStandardOutput = true;
            ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

            using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
            {
                proc.StartInfo = ps;
                proc.Exited += new EventHandler(proc_Exited);
                proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived);
                proc.Start();
                proc.WaitForExit();
                proc.BeginOutputReadLine();
                while (!proc.HasExited) ;
            }
        }

        void proc_Exited(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended");
            if (this.sbRedirectedOutput.ToString().IndexOf("Oops, write failed") > -1){
               MessageBox.Show(this, "Error in opening Cash Drawer");
            }
            if (this.sbRedirectedOutput.ToString().IndexOf("Drawer Ok") > -1){
               MessageBox.Show(this, "Drawer Ok");
            }
        }

        void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            if (e.Data != null) this.sbRedirectedOutput.Append(e.Data + Environment.NewLine);
            //System.Diagnostics.Debug.WriteLine("proc_OutputDataReceived: Data: " + e.Data);
        }

进程 shell 到一个隐藏窗口,所有输出都被重定向并在事件处理程序中处理......这应该可以解决问题。请注意,重定向的输出如何进入 sbRedirectedOutput(StringBuilder 实例)。在 proc_ProcExited 事件处理程序中,它检查 sbRedirectedOutput 中是否有 QB4.5 程序发出的消息“Oops Write failed”。

请注意,您可能需要将 QB4.5 的运行时库包含在同一目录中...不是 100% 确定...已经好几年了...

您觉得怎么样?

希望这有帮助,
此致,
汤姆.

Are you sure you're supposed to send out this code? I would have always thought that the code is prefixed by ESC i.e. 0x1b hexadecimal...for cash drawers...

"\x1bA"

Interesting that double 'A' is used...oh well... :)

Edit: After thinking about this I realized there is another way of doing it, read on...
I have modified your original BASIC code with a bit of bullet-proofing...save it to opendrawer.bas

Sub OpenDrawer()
drawerComPort = "COM1"
Open drawerComPort For Output Access Write As #1
REM ADDED ERROR HANDLING
ON ERROR GOTO ErrHandler
Print #1, Chr$(65); "A";
Close #1
print "Drawer Ok"
OpenDrawer_Exit:
On Error Goto 0
Exit Sub
ErrHandler:
print "Oops, Write Failed"
Goto OpenDrawer_Exit
End Sub

REM The Main....
OpenDrawer

Download the old QB4.5 MS-Quick Basic compiler, and compile that to an executable, into opendrawer.exe, the QB4.5 can be found here. Now, the onus is on you to make this bulletproof, i.e. what happens if writing to COM1 fails, issue a message like in the example BASIC code I modified

Then you can use the System.Diagnostics.Process to shell out using a hidden window

    public class TestDrawer
    {
        private StringBuilder sbRedirectedOutput = new StringBuilder();
        public string OutputData
        {
            get { return this.sbRedirectedOutput.ToString(); }
        }
        public void Run()
        {
            System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo();
            ps.FileName = "opendrawer";
            ps.ErrorDialog = false;
            ps.CreateNoWindow = true;
            ps.UseShellExecute = false;
            ps.RedirectStandardOutput = true;
            ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

            using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
            {
                proc.StartInfo = ps;
                proc.Exited += new EventHandler(proc_Exited);
                proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived);
                proc.Start();
                proc.WaitForExit();
                proc.BeginOutputReadLine();
                while (!proc.HasExited) ;
            }
        }

        void proc_Exited(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended");
            if (this.sbRedirectedOutput.ToString().IndexOf("Oops, write failed") > -1){
               MessageBox.Show(this, "Error in opening Cash Drawer");
            }
            if (this.sbRedirectedOutput.ToString().IndexOf("Drawer Ok") > -1){
               MessageBox.Show(this, "Drawer Ok");
            }
        }

        void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            if (e.Data != null) this.sbRedirectedOutput.Append(e.Data + Environment.NewLine);
            //System.Diagnostics.Debug.WriteLine("proc_OutputDataReceived: Data: " + e.Data);
        }

The process shells out to a hidden window and all output is redirected and handled in the event handler...that should do the trick. Notice, how the redirected output goes into the sbRedirectedOutput (a StringBuilder instance). In the proc_ProcExited event handler, it checks the sbRedirectedOutput for the message 'Oops Write failed' which would be issued from the QB4.5 program.

Be aware, that you may need to include the QB4.5's run-time library in the same directory...not 100% sure...it's being years...

What do you think?

Hope this helps,
Best regards,
Tom.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文