/*
Copyright 2010 GHI Electronics LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Diagnostics;
namespace FezTerm
{
///
/// FezTermClient is the term client that runs on the PC side.
///
public class FezTermClient
{
public event Action MessageReceived;
public event Action TermError;
private readonly byte delimByte = 255;
SerialPort port;
public FezTermClient(SerialPort port, byte delimByte)
{
if (port == null) throw new ArgumentNullException("port");
this.port = port;
this.delimByte = delimByte;
Debug.WriteLine("");
}
public bool IsOpen
{
get { return port.IsOpen; }
}
public void Start()
{
if (!this.port.IsOpen)
this.port.Open();
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
}
void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
var ev = TermError;
if (ev != null)
ev(new Exception("Comm error."));
}
public void Close()
{
if (this.port.IsOpen)
this.port.Close();
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string msg = ReadStringUntil(this.port, delimByte);
var ev = MessageReceived;
if (ev != null)
ev(msg);
}
// Read port until delim is seen. Return as string using UTF8.
private string ReadStringUntil(SerialPort port, byte delim)
{
List list = ReadBytesUntil(port, delim);
if (list.Count() == 0) return null;
byte[] ba = list.ToArray();
string s = Encoding.UTF8.GetString(ba);
return s;
}
// Read port until delim is seen. Return all prior bytes.
private List ReadBytesUntil(SerialPort port, byte delim)
{
List list = new List();
byte[] buf = new byte[1];
while (true)
{
int read = port.Read(buf, 0, 1);
if (read == 0)
return list;
if (buf[0] == delim)
return list;
list.Add(buf[0]);
}
}
///
/// Write a message to the comm port. Message marker is delim byte.
///
public int WriteMessage(string line)
{
if (line == null) throw new ArgumentNullException("line");
if (!port.IsOpen) return 0;
byte[] ba = Encoding.UTF8.GetBytes(line);
this.port.Write(ba, 0, ba.Length);
this.port.Write(new byte[]{this.delimByte}, 0, 1);
return ba.Length + 1;
}
}
}