本帖最后由 Zoologist 于 2017-12-30 14:24 编辑
继续上次的话题,我选择 C# 来实现,主要是因为语言简单,特别是在界面开发所见即所得。如果说20年前的Delphi是 VB Killer的话,眼下 C# 也能称得上Delphi Killer了。不由得发出“风轮流转”的感叹。 从界面入手,介绍功能:左右放置两个TrackBar用来控制左右轮子的速度,上方放置2个控制LED的Button(具体的做法是Button上显示图片,通过ImageList来进行切换),一个 Text输入框用来输入小车的IP,剩下的大按钮是用来控制车前灯。
除了这些可见的控件之外,还有下面三个不可见的控件,2个ImageList是给Button显示图标用的,一个 Timer是用来每隔100ms发送命令用到(发出的命令是左右轮子转动加持续100ms,这样就能做到连续运行)。同时Trackbar如果有一个数值低于30就直接停止。
完整代码如下:
[kenrobot_code]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
namespace Tempshow
{
public partial class Form1 : Form
{
// Telnet 对象
TelnetConnection tc;
// 前灯是否有改变的标记,如果有改变我们才发送命令给小车
Boolean LedChanged = false;
public Form1()
{
InitializeComponent();
}
//左车灯按钮
private void button1_Click(object sender, EventArgs e)
{
// ImageIndex 为 0 表示关,1表示开
if (this.button1.ImageIndex == 0) { this.button1.ImageIndex = 1; }
else { this.button1.ImageIndex = 0; }
LedChanged = true;
}
//右车灯按钮
private void button2_Click(object sender, EventArgs e)
{
// ImageIndex 为 0 表示关,1表示开
if (this.button2.ImageIndex == 0) { this.button2.ImageIndex = 1; }
else { this.button2.ImageIndex = 0; }
LedChanged = true;
}
//连接小车的按钮
private void button3_Click(object sender, EventArgs e)
{
if (this.button3.ImageIndex == 0) {
this.button3.ImageIndex = 1;
this.textBox1.Enabled = true;
timer1.Enabled = false;
if (tc.IsConnected) {
tc.DisConnect();
}
}
else {
// 创建 Telnet 连接
tc = new TelnetConnection(textBox1.Text, 23);
string s = tc.Login(" ", " ", 100);
// 正确连接之后
if (tc.IsConnected) {
// 改变连接的图标
button3.ImageIndex = 0;
// 不可以输入 Ip
textBox1.Enabled = false;
//打开定时器
timer1.Enabled = true;
}
}
}
//每隔100ms发生一次的定时器
private void timer1_Tick(object sender, EventArgs e)
{
string led="M6 ";
if (LedChanged) {
if (button1.ImageIndex==0) {
//发送开左灯
led += "0 ";
} else
{
//发送关左灯
led += "1 ";
}
if (button2.ImageIndex == 0)
{
//发送开右灯
led += "0";
}else
{
//发送关右灯
led += "1";
}
tc.WriteLine(led);
LedChanged = false;
}
if ((trackBar1.Value<30) || (trackBar2.Value <30)) {
tc.WriteLine("M200 0 0 0");
}
else {
string Motor = "M200 " + trackBar1.Value.ToString() + " "+trackBar2.Value.ToString() + " 100";
tc.WriteLine(Motor);
}
}
}
enum Verbs
{
WILL = 251,
WONT = 252,
DO = 253,
DONT = 254,
IAC = 255
}
enum Options
{
SGA = 3
}
class TelnetConnection
{
TcpClient tcpSocket;
int TimeOutMs = 1 * 1000;
public TelnetConnection(String Hostname, int Port)
{
tcpSocket = new TcpClient(Hostname, Port);
}
public string Login(string Username, string Password, int LoginTimeOutMs)
{
int oldTimeOutMs = TimeOutMs;
TimeOutMs = LoginTimeOutMs;
// string s;
// string s = Read();
// if (!s.TrimEnd().EndsWith(":"))
// throw new Exception("Failed to connect : no login prompt");
// WriteLine(Username);
//s += Read();
//if (!s.TrimEnd().EndsWith(":"))
// throw new Exception("Failed to connect : no password prompt");
// WriteLine(Password);
WriteLine("M0");
string s = Read();
TimeOutMs = oldTimeOutMs;
return s;
}
public void DisConnect()
{
if (tcpSocket != null)
{
if (tcpSocket.Connected)
{
tcpSocket.Client.Disconnect(true);
}
}
}
public void WriteLine(string cmd)
{
Write(cmd + "\r\n");
}
public void Write(string cmd)
{
if (!tcpSocket.Connected) return;
byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
tcpSocket.GetStream().Write(buf, 0, buf.Length);
}
public string Read()
{
if (!tcpSocket.Connected) return null;
StringBuilder sb = new StringBuilder();
do
{
ParseTelnet(sb);
System.Threading.Thread.Sleep(TimeOutMs);
} while (tcpSocket.Available > 0);
return ConvertToGB2312(sb.ToString());
}
public bool IsConnected
{
get { return tcpSocket.Connected; }
}
void ParseTelnet(StringBuilder sb)
{
while (tcpSocket.Available > 0)
{
int input = tcpSocket.GetStream().ReadByte();
switch (input)
{
case -1:
break;
case (int)Verbs.IAC:
// interpret as command
int inputverb = tcpSocket.GetStream().ReadByte();
if (inputverb == -1) break;
switch (inputverb)
{
case (int)Verbs.IAC:
//literal IAC = 255 escaped, so append char 255 to string
sb.Append(inputverb);
break;
case (int)Verbs.DO:
case (int)Verbs.DONT:
case (int)Verbs.WILL:
case (int)Verbs.WONT:
// reply to all commands with "WONT", unless it is SGA (suppres go ahead)
int inputoption = tcpSocket.GetStream().ReadByte();
if (inputoption == -1) break;
tcpSocket.GetStream().WriteByte((byte)Verbs.IAC);
if (inputoption == (int)Options.SGA)
tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WILL : (byte)Verbs.DO);
else
tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WONT : (byte)Verbs.DONT);
tcpSocket.GetStream().WriteByte((byte)inputoption);
break;
default:
break;
}
break;
default:
sb.Append((char)input);
break;
}
}
}
private string ConvertToGB2312(string str_origin)
{
char[] chars = str_origin.ToCharArray();
byte[] bytes = new byte[chars.Length];
for (int i = 0; i < chars.Length; i++)
{
int c = (int)chars;
bytes = (byte)c;
}
Encoding Encoding_GB2312 = Encoding.GetEncoding("GB2312");
string str_converted = Encoding_GB2312.GetString(bytes);
return str_converted;
}
}
}[/kenrobot_code]
Windows平板和普通的PC 笔记本没有差别,只是更轻薄
工作的视频
|