I need to detect when someone is connected to my computer. I have an incoming connection enabled, and need to know when a user is connected. Preferably from a script in CSharp
Generally, regardless of language, the approach is to open a serial port to talk to the modem. For .NET, you might want to refer to System.IO.Ports.SerialPort. The connection parameters (baud rate, data bits, stop bits, parity, flow control) depends on the device in question. Try 57600 or the fastest speed of your serial port, 8 databits, 1 stop bit, no parity and hardware flow control; that's what's typically used.
Hayes compatible modems spend "RING" notifications (plan text) over a serial port when someone is dialling. You'd send an "AT A" to the modem to anwer the call (or the modem may be configured for auto answer). When a connection is established, a "CONNECT XXX" is sent from the modem, where XXX is the connection details. For a summary of Hayes commands, see this Wikipedia link. (It also describes details such as command/data mode that you'll probably need to go into, if you want to program communications over a modem connection.)
Attach a DataReceived event to the serial port you have opened
Look at the SerialPort documentation on how to open the port and attach handlers. you need to know the port speed and stop, start bits, parity, etc. Try speed of 9600 (bps), parity.none, no handshaking, 1 stop and start bits... best thing to do is leave everything at the default and just do new SerialPort("COM5") or whatever your com port is so you leave things at their default values.
Keep putting the received data into a buffer and keep scanning that buffer for "RING".
your serial port will literally receive the word "ring" when your modem is ringing. so you've gotta keep scanning for it.
Also, the reason why I say put your data in a buffer is because sometimes it arrives out of sequence. or you might want to do a readLine so it reads till the /r (carriage return) that indicates one complete response
Related
I'm trying to send this byte array: 0x7E 0x02 0x40 0x01 0x00 0x06 0xDA 0x7E
through a serial port but it has to be serialized first. I'm not sure how to go about that. I also have to deserialized the data coming in from the serial port. How would I go about doing that?
The protocol data unit on a serial port is bytes; there is no need to serialise them. You can simply write the bytes to the serial port, and you'll get those bytes coming out of the other end of the cable.
How serial ports behave can be a bit tricky. Unixes like Linux often think of them as "text" devices and so start interpreting the byte stream coming in as if you were typing it on a keyboard (so a ^H 0x08 is backspace and is interpreted as such). So you have to be careful to configure the serial port to be a raw, binary interface.
If the port is text only, well that's where binary encoding like base64 come in, it's effectively a text serialisation for bytes.
You also need to get configuration and wiring right; using hardware flow control and got the corresponding wires connected?
And then there's message demarcation. And depending on what flow control you've configured there's nothing to stop the sending end if the receiving end is not running, so you can have a start up order problem.
Basically serial ports are a damned nuisance to use, and protocols like xmodem and ymodem were developed to make transfers reliable. if you want a serial port to exchange datagrams (well, files) as reliably and as certainly as, say, a tcp network socket you need to use something like xmodem or ymodem between your application and the serial port. The problem is that these are ancient tech, but there appears to be some implementations.
I want to know if I put these in my code, does computer send any kind of signal to the device?
SerialPort myport = new SerialPort("COM1");
myport.DtrEnable = true;
myport.RtsEnable = true;
I'm required to send a signal on specific pins to the device. As I know Dtr and Rts use pins 4 and 7. So when I write the code above, will my computer send a signal on pins 4 and 7? Or is there a simple way to send a signal on a specific pin?
Sure, these properties control the state of the handshake signals. Their use is not arbitrary, a properly designed serial port device pays attention to them. DTR is Data Terminal Ready, normally connected to DSR (Data Set Ready) on the device. The device assumes that your computer is simply not turned on or the cable is disconnected when DSR is off. It won't send anything and ignores anything you send to it when the signal is off.
RTS is Request To Send, normally connected to CTS (Clear To Send) on the device. Normally used for flow control, it prevents the device from sending too much data and overflow the receive buffer. A nasty problem that is very hard to recover from, the data is entirely lost.
You should normally set the SerialPort.Handshake property to HandShake.RequestToSend so the driver does this automatically. A very common bug is to leave it set to Handshake.None, now you have to turn on these signals yourself. And you'll risk buffer overflow of course, albeit that you'd have to write very slow code to ever get in the danger zone. It has been done.
These signals can be used in hobby projects to control, say, a reed relay. Do beware that the voltages on the signal lines are unpredictable (swings between +/- 5 to 24 Volts) and can't supply a lot of amps (usually 20 milliamps max). You need at least a diode, typically a transistor to switch a heavier load. Ask about it at electronics.stackexchange.com
In theory: Yes. Whatever you have connected to your serial port will see something. It won't be data, but if it is checking its pin states, it will know that you have done something.
In practice: Maybe. Being able to accurately detect these pin states is heavily dependent on the cable being used. Here is a recent post that goes over the cable related issues with these pin states.
I am trying to read data from the serial port. The data comes off of a scale. I first send a command to start reading the scale.
_serialPort.Write("P");
then after waiting for some time I am trying to read using
temp2 = _serialPort.ReadLine();
The application hangs at this line of code. I have also tried the Read function but am getting the same result. ReadExisting() function returns an empty string.
As the ReadLine() is not timing out or throwing any exceptions I am unable to debug this issue as I have no further information. The port cannot be defective as WriteLine() and ReadExisting() are working.
Any help would be appreciated.
Thanks
Try this behind your recieve button:
string msg = serialObj.ReadExisting();
MessageBox.Show(msg);
With comms, start with a terminal program. That is a program that lets you type commands that are sent out of the serial port to your device, and displays any text that comes back from the device. This will allow you to try out the protocol you've described and see what the device sends back. Once you get the correct response, you know:
The device is working
The serial cable is correctly wired and working
You are using the correct port settings (baud rate, stop bits, parity, etc)
You understand what the protocol is (do you send a "P" or a "P" followed by a newline?)
Then you can run your code in the knowledge that if it doesn't work, it's something in your code that is wrong, not any other factors muddying the waters.
Once you send the initial command, you can read the serial port immediately for the response - the call you are using will simply wait until some data is received. If no data is received, it will wait forever (hence your program hang). Any of the above things being incorrect will cause the same symptom of not receiving any data. And changing the way you read the data (e.g. async reads etc) will not change the fact that there is no data being received.
The other thing to be careful of is port settings. Generally, start with the default settings for most things (as RS232 is used in a pretty standard way by most devices) - a typical beginner mistake is to explicitly set options like the Handshaking approach, but if you get it wrong it'll break the comms. Usually you'd specify a baud rate and 8N1 (8 bits, no parity, 1 stop bit) and leave the other settings alone until you find they need to be set to get anything wto work, or you know (as in their manual states it in black and white) that your device requires something different.
Change your Write function to WriteLine. That may help. In addition, take a look at the sample of this link at MSDN. It is helpful.
Check that the SerialPort.NewLine property is set correctly. If you receive a CR character only, and the ReadLine expect eg. CRLF, your application will hung.
Does the scale respond to each "P" sent to it, or is "P" a command that tells it to begin sending a continuous stream of data? To use a terminal program, set its baud rate and protocol to the same as the scale (and your program), and use it to send a "P" to the scale in place of doing that with your program. Any response from the scale should appear in the terminal window. I prefer termie or termite (both downloadable) hyperterminal is pretty bad.
you can use that part to send a data to serial port from c#:
int MyInt3 = Convert.ToInt32(textBox3.Text);
byte[] p = BitConverter.GetBytes(MyInt3);
serialPort1.Write(p, 0, 1);
And after that you can use Read() method.
Hi Is there any way to connecting to computers via Dial Modem without internet?
Like windows Hyper terminal.
making connection sending files between computers.
Just Connection Between two Computers Directly and sending FIle.
Yes.
Assuming the modems are connected via a serial port (or emulate being connected via a serial port): you'll need one modem set up (learn your AT commands!) to listen for and answer incoming calls, and the other to dial the first.
You can then treat the pair as a rather long serial link.
However getting everything to work reliably is more of an art than a science, and something that is so rarely done today that much of it is forgotten. The last time I worked with modems in this way was more than fifteen years ago.
The way we used to do it back in the olden days was with a null-modem cable. We even used to do "networked" gaming that way, back in the day.
This is bascially an RS-232 cable with the receive and transmit pins crosswired. I still see some adapters around, so it shouldn't be too tough to get hold of one.
Much later some people created SLIP (Serial Line IP) to enable a serial line to act as a carrier for the entire TCP/IP stack. A bit later PPP was introduced as an improvement. I think SLIP is still available for most platforms, and PPP exists on every platform that can do dial-up internet.
So if the question basically boils down to wanting to network two computers via PPP without going through somebody else's dial-up server (like Earthlink), what you need is to install a PPP server on one of the two machines. They come with most Linux distros. For Windows you will have to go look. I'd help, but my corporate blocker is being overexuberant again.
Someone has written an XModem implementation in C# here: http://trackday.cc/b2evo/blog2.php/2007/08/02/net-xmodem It may help with what you're after.
One thing that's not clear from your question is whether you are attempting to directly connect two machines in the same physical location with a cable, or if you are attempting to dial in to one from the other over a PSTN.
If they are in the same place, eliminate the modem from the equation. This reduces complexity significantly.
If they are in separate locations (ie, dialing over an honest-to-God dial-up connection), there is some code here that might help you. The article talks about a Bluetooth or GPRS modem, but the core of it is about sending AT commands which can be used to talk to any AT-command set-compatible device. It might get you going in the right direction.
Update
See http://msdn2.microsoft.com/en-us/system.io.ports.serialport(VS.80).aspx
Since a modem should be attached to a COM port (COM1-COM12) even it is an internal modem, you should be able to use the .NET framework's SerialPort class to open the port, send AT commands, etc. Once you have an open connection, you could use the XModem library to transfer files, or straight serial for regular communications.
Do you need an IP stack, or are you happy with a straight serial protocol?
You can quite easily setup dial-up network connections within Windows that require the use of a modem (its under the option for setting up a VPN, but you can set it for just a dial up).
So I would assume that you can then map a network location to it for use by your C# code.
As already stated at least one of the modems must be on and listening for a connection.
* edit *
I believe that the following code will trigger a dial-up connection that has been placed within Network Connections
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(#"c:\Local Area Connection 2 - Shortcut");
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
For link placed at c:\ drive and named "Local Area Connection 2 - Shortcut"
You could then ping the destination to see if its connected.
Ultimately though I think that your best solution may be to use RAS.
Have a look here at Codeplex: DotRAS
You can then use the following code:
RasDialer dialer = new RasDialer();
bool connected = false;
foreach (RasConnection connection in dialer.GetActiveConnections())
{
if (connection.EntryName == "MyFriendsPC")
{
connected = true;
break;
}
}
if (!connected) {
dialer.EntryName = "MyFriendsPC";
dialer.Dial();
// If you need to provide credentials, use the Dial(NetworkCredential) overload that's available.
}
This example assumes you already have an entry named MyFriendsPC in the default phone book. If you do not and need to create this connection programmatically, you can use the RasPhoneBook component for that.
RasPhoneBook pbk = new RasPhoneBook();
pbk.Open(); // This will open the phone book in the All Users profile.
RasEntry entry = new RasEntry("MyFriendsPC");
If you'd rather use the default settings for the connection you can use one of the static methods on the RasEntry class, or manually configured the connection here.
pbk.Entries.Add(entry);
Once the entry has been added to the collection, it will immediately be added into the phone book.
I recently wanted to connect a dial-up POS terminal to an analog modem. This is not difficult, but you need to introduce a 9-volt battery and a 200mA resistor in parallel for the modems to connect. https://www.youtube.com/watch?v=luarFqislIc describes the approach (skip to 11:30 to see the circuit). Without the battery and resistor to provide the loop current (about 18mA), the modems will not negotiate a connection (you'll hear the modem after entering ATA to answer, but you won't hear the final part of the modem negotiation). With the loop current, the modems will connect. The video even shows ZModem being used to transfer a file from one PC to the other.
One final item not mentioned in the video is with this circuit, there is no dial tone. To get around this, enable blind dialing (ATX1) on the calling modem. Also, since there are no rings with this approach, setting the receiving modem to auto-answer (ATS0=1) won't work. You have to enter ATA on the receiving modem to answer.
We are trying to emulate a POS keyboard in order to integrate an application with an existing Point of Sale application.
We ran across this software: Virtual Serial Port Kit
It basically creates a virtual serial port pair so that data send to COM1 can come out of COM4 and vice versa. This allows our application to send data through COM4 to appear to the POS application that it is talking to a keyboard on COM1.
Pretty ingenious, but it seems there is some kind of signalling going on that we are not able to replicate with the .Net System.IO.Ports.SerialPort class...
From what we can tell from serial port monitoring programs, this is how the startup sequence works:
8 byte Command sent to keyboard
Keyboard beeps
Some kind of signal is sent from the keyboard
Second 8 byte command is sent to keyboard, triggered by the signal
Keyboard replies with device and version information
When using our virtual serial port, we cannot figure out how to replicate the signal sent from the keyboard. We can see all data coming through properly, so we believe the settings on our SerialPort object are correct. Here is a snippet of our SerialPort settings:
_port.BaudRate= 9600;
_port.Parity = Parity.None;
_port.DataBits = 8;
_port.StopBits = StopBits.One;
_port.DtrEnable = true;
_port.RtsEnable = true;
We also noticed from using portmon we see a GET_MODEM_STATUS request that is what the POS application is waiting on before sending the second command.
Any ideas on how to diagnose this? Since we are using .NET this whole situation is a little more low level than we're used to.
UPDATE: I also want to note that we tried the SDK here: Franson Serial Tools but we could not even get data to go through when using this SDK.
UPDATE: We have thrown out using any kind of virtual serial port. We have gotten a cable to run from the POS PC to another and can see data coming across to emulate the keyboard. Now our problem is that we can't figure out how to signal that the keyboard is ready to recieve data as the top answer mentions. It appears that the POS application sends the command to beep an waits up to 3 seconds waiting for a signal. So it times out when talking to our application, but not when talking to the real keyboard
How can we do this with the SerialPort class? We already set DtrEnable and RtsEnable to true, do we need to set something else? Or do we have to use a lower level serial port p/invoke to accomplish this?
SOLUTION:
_port.RtsEnabled = false;
Thread.Sleep(1000);
_port.RtsEnabled = true;
This makes the POS application think the keyboard is plugged in, which makes sense. I'll mark the #1 answer as the answer since it greatly helped us find the solution.
EDITED to give more perspective from the point of view of simulating the keyboard.
As it happens I have written low-level drivers for the 92R keyboard in the distant past.
You really need the documentation for the proprietary protocol to do this properly - for example commands sent to the keyboard contain a sequence number and a checksum. I'd recommend contacting Fujitsu and attempting to get hold of this documentation.
From what you've described:
The first 8-byte command you sent was probably a reset command (as it caused the keyboard to beep). The keyboard sends a response to acknowledge the command, then resets itself.
After sending a reset command, the POS app needs to wait for the keyboard to reset (I think about 3000ms) before sending other commands.
It looks like the second send is a command to request the firmware version.
The POS app will also need to subsequently send a command to enable "autoinput" before the keyboard will actually send keystrokes.
There are also commands available to request the keylock position, sound the tone generator, enable/disable the MSR, and write to the optional embedded 2-line display. So your simulator will need to be capable of reproducing the responses to these commands.
Once the POS app has enabled "autoinput" the keyboard will send unsolicited messages with the keystrokes being pressed (or keylock position changes, or MSR input). IIRC these messages also have a sequence number and checksum that you will need to reproduce in your simulator.
The only signalling I know of is that the keyboard raises CTS when it is ready to receive data. If you connect two ports on a PC, you need a special null modem cable (see below) so that when your simulator raises RTS on COM4 it will be seen as CTS on the other port.
The COM ports on a TeamPOS motherboard provide power to the keyboard. You probably don't want to connect these pins to your COM4 port, so I would suggest using a null modem cable that connects only the following pins:
2 (Tx data) - 3 (Rx data)
3 (Rx data) - 2 (Tx data)
7 (RTS) - 8 (CTS)
8 (CTS) - 7 (RTS)
I've not done serial port development for years, but when I did I always used a Crossover Cable and a second PC running Windows HyperTerminal.