获得传感器消息
标题虽然这么长,但是做法却十分简单 总共分为两个步骤 第一:获取传感器消息 第二:传给mqtt网络 第三:网页根据mqtt消息采取动作 总结:就是硬件上面操作,网页上实时查看硬件的操作动作 我们先来看第一个:获取传感器消息 首先看一下c#中对于串口通讯的操作(急于实现功能的各位可以跳过直接看下面的源码)
名 称 | 说 明 |
---|---|
BaseStream | 获取 SerialPort 对象的基础 Stream 对象 |
BaudRate | 获取或设置串行波特率 |
BreakState | 获取或设置中断信号状态 |
BytesToRead | 获取发送缓冲区中数据的字节数 |
BytesToWrite | 获取端口的载波检测行的状态 |
CDHolding | 获取“可以发送”行的状态 |
CtsHolding | 获取或设置每个字节的标准数据位长度 |
DiscardNull | 获取或设置一个值,该值指示 Null 字节在端口和接收缓冲区之间传输时是否被忽略 |
DsrHolding | 获取数据设置就绪 (DSR) 信号的状态 |
DtrEnable | 获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号 |
Encoding | 获取或设置传输前后文本转换的字节编码 |
Handshake | 获取或设置串行端口数据传输的握手协议 |
IsOpen | 获取一个值,该值指示 SerialPort 对象的打开或关闭状态 |
NewLine | 获取或设置用于解释 ReadLine( )和WriteLine( )方法调用结束的值 |
Parity | 获取或设置奇偶校验检查协议 |
ParityReplace | 获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节 |
PortName | 获取或设置通信端口,包括但不限于所有可用的 COM 端口 |
ReadBufferSize | 获取或设置 SerialPort 输入缓冲区的大小 |
ReadTimeout | 获取或设置读取操作未完成时发生超时之前的毫秒数 |
ReceivedBytesThreshold | 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数 |
RtsEnable | 获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号 |
StopBits | 获取或设置每个字节的标准停止位数 |
WriteBufferSize | 获取或设置串行端口输出缓冲区的大小 |
WriteTimeout | 获取或设置写入操作未完成时发生超时之前的毫秒数 |
名 称 | 说 明 |
---|---|
Close | 关闭端口连接,将 IsOpen 属性设置为False,并释放内部 Stream 对象 |
Open | 从 SerialPort 输入缓冲区中读取 |
Read | 从 SerialPort 输入缓冲区中读取 |
ReadByte | 从 SerialPort 输入缓冲区中同步读取一个字节 |
ReadChar | 从 SerialPort 输入缓冲区中同步读取一个字符 |
ReadLine | 一直读取到输入缓冲区中的 NewLine 值 |
ReadTo | 一直读取到输入缓冲区中指定 value 的字符串 |
Write | 已重载。将数据写入串行端口输出缓冲区 |
WriteLine | 将指定的字符串和 NewLine 值写入输出缓冲区 |
首先要添加
using System.IO; using System.IO.Ports;
1...在类的内部定义SerialPort com;
2...打开串口
com = new SerialPort(); com.BaudRate = ; com.PortName = "COM1"; com.DataBits = ; com.Open();//打开串口
3...发送数据
Byte[] TxData ={1,2,3,4,5,6,7,8 }; com.Write(TxData, , );
4...接收数据
using System; using System.IO.Ports; using System.Linq; using System.Management; using System.Threading; using System.Windows.Forms; namespace CefSharp.MinimalExample.WinForms { public static class COMCtrl { public static string portName = ""; public static int baudRate = ; public static Parity parity = Parity.None; public static int dataBits = ; public static StopBits stopBits = StopBits.One; public static string[] data;//用于存储6位数据 static SerialPort sp = null;//串口控制 public static string sensorNum = "";//传感器的序号 static CalcOnCrc16 OnCrc16; public static string audioName; public static void Init() { OnCrc16 = new CalcOnCrc16(); portName = GetPortName(); OpenPort(); } #region 打开与关闭端口 //获取 static string GetPortName() { string i = GetComNum().ToString(); return "COM" + i; } //打开端口 public static void OpenPort() { sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits); try { sp.Open(); sp.ReadTimeout = ; } catch (Exception ex) { MessageBox.Show(ex.Message); } } //关闭端口 public static void ClosePort() { try { sp.Close(); } catch (Exception ex) { MessageBox.Show("端口关闭失败" + ex.Message); } } #endregion static string Lock_Str = "Lock"; #region 获取端口号 public static int GetComNum() { int comNum = -1; string[] strArr = GetHarewareInfo(HardwareEnum.Win32_PnPEntity, "Name"); foreach (string s in strArr) { if (s.Length >= && s.Contains("CH340")) { int start = s.IndexOf("(") + ; int end = s.IndexOf(")"); comNum = Convert.ToInt32(s.Substring(start + , end - start - )); } } return comNum; } private static string[] GetHarewareInfo(HardwareEnum hardType, string propKey) { System.Collections.Generic.List<string> strs = new System.Collections.Generic.List<string>(); try { using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + hardType)) { var hardInfos = searcher.Get(); foreach (var hardInfo in hardInfos) { if (hardInfo.Properties[propKey].Value != null) { String str = hardInfo.Properties[propKey].Value.ToString(); strs.Add(str); } } } return strs.ToArray(); } catch { return null; } finally { strs = null; } } public enum HardwareEnum { // 硬件 Win32_Processor, // CPU 处理器 Win32_PhysicalMemory, // 物理内存条 Win32_Keyboard, // 键盘 Win32_PointingDevice, // 点输入设备,包括鼠标。 Win32_FloppyDrive, // 软盘驱动器 Win32_DiskDrive, // 硬盘驱动器 Win32_CDROMDrive, // 光盘驱动器 Win32_BaseBoard, // 主板 Win32_BIOS, // BIOS 芯片 Win32_ParallelPort, // 并口 Win32_SerialPort, // 串口 Win32_SerialPortConfiguration, // 串口配置 Win32_SoundDevice, // 多媒体设置,一般指声卡。 Win32_SystemSlot, // 主板插槽 (ISA & PCI & AGP) Win32_USBController, // USB 控制器 Win32_NetworkAdapter, // 网络适配器 Win32_NetworkAdapterConfiguration, // 网络适配器设置 Win32_Printer, // 打印机 Win32_PrinterConfiguration, // 打印机设置 Win32_PrintJob, // 打印机任务 Win32_TCPIPPrinterPort, // 打印机端口 Win32_POTSModem, // MODEM Win32_POTSModemToSerialPort, // MODEM 端口 Win32_DesktopMonitor, // 显示器 Win32_DisplayConfiguration, // 显卡 Win32_DisplayControllerConfiguration, // 显卡设置 Win32_VideoController, // 显卡细节。 Win32_VideoSettings, // 显卡支持的显示模式。 // 操作系统 Win32_TimeZone, // 时区 Win32_SystemDriver, // 驱动程序 Win32_DiskPartition, // 磁盘分区 Win32_LogicalDisk, // 逻辑磁盘 Win32_LogicalDiskToPartition, // 逻辑磁盘所在分区及始末位置。 Win32_LogicalMemoryConfiguration, // 逻辑内存配置 Win32_PageFile, // 系统页文件信息 Win32_PageFileSetting, // 页文件设置 Win32_BootConfiguration, // 系统启动配置 Win32_ComputerSystem, // 计算机信息简要 Win32_OperatingSystem, // 操作系统信息 Win32_StartupCommand, // 系统自动启动程序 Win32_Service, // 系统安装的服务 Win32_Group, // 系统管理组 Win32_GroupUser, // 系统组帐号 Win32_UserAccount, // 用户帐号 Win32_Process, // 系统进程 Win32_Thread, // 系统线程 Win32_Share, // 共享 Win32_NetworkClient, // 已安装的网络客户端 Win32_NetworkProtocol, // 已安装的网络协议 Win32_PnPEntity,//all device } #endregion //发送数据 public static void WriteData(byte[] bys) { if (sp.IsOpen) { sp.Write(bys, , bys.Length); //需要延迟执行接收程序 Thread.Sleep(); lock (Lock_Str) { DataReceiveFunction(); } } } //获取传感器状态 public static void GetSensorState() { //发送获取传感器代码 WriteData(strToToHexByte("01 02 00 00 00 1E F8 02")); } //TO => 16进制 public static byte[] strToToHexByte(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % ) != ) hexString += " "; byte[] returnBytes = new byte[hexString.Length / ]; for (int i = ; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * , ), ); return returnBytes; } //接收消息 #region constanc static byte[] MSG;//接收到硬件返回的字符 static byte[] buffer = new byte[];//硬件返回数组的缓存空间 static int buffLength = ; static string Allbytes = ""; static string CheckCRC = ""; static string oldStr = "00000000000000000000000000000000"; //旧字符 static string newStr= "00000000000000000000000000000000"; //新字符 #endregion public static void DataReceiveFunction() { if (sp != null && sp.IsOpen) { try { Array.Clear(buffer, , buffer.Length); buffLength = sp.Read(buffer, , buffer.Length); MSG = new byte[buffLength - ]; Array.Copy(buffer, , MSG, , buffLength - ); //MCU返回的字符串转换为十六进制输出 for (int i = ; i < buffLength; i++) { Allbytes += buffer[i].ToString("X2") + " "; } //MessageBox .Show (buffLength + "--------" + Allbytes); //切割后2位的字符串,用来crc校验 string Checkbytes = ""; for (int i = ; i < MSG.Length; i++) { Checkbytes += MSG[i].ToString("X2") + " "; } CheckCRC += buffer[buffLength - ].ToString("X2"); CheckCRC += buffer[buffLength - ].ToString("X2"); //BrowserForm.browserForm.RecMqttMsg.Text = CheckCRC ; //MessageBox .Show("CRC16计算:" + OnCrc16.CRC16(MSG).ToString("X4")); if (CheckCRC == (OnCrc16.CRC16(MSG).ToString("X4"))) { CheckCRC = ""; byte[] reverse = new byte[]; //硬件返回的传感器反序数组 Array.Copy(MSG, , reverse, , ); byte[] forward = new byte[]; //传感器正向数组 for (int i = ; i < ; i++) { forward[i] = reverse[reverse.Count() - i - ]; } string sensorStr = ""; for (int i = ; i < ; i++) { sensorStr += Convert.ToString(forward[i], ).PadLeft(, '0');//一位16进制的数转换为8个单位 } newStr = ReverseD(sensorStr); //字符串有变化开始推送消息 if (newStr.CompareTo(oldStr) == ) { } else { oldStr = newStr; //int i = oldStr.IndexOf("1"); //if (i != -1) //{ BrowserForm.browserForm.RecMqttMsg.Text = oldStr; //发送消息 MqttCtrl.client_sendMsg(oldStr); //} } } else { Console.WriteLine("检测未通过!"); } Array.Clear(MSG, , MSG.Length); } catch (Exception ex) { Array.Clear(MSG, , MSG.Length); MessageBox.Show(ex.Message); //如果出错就再调用一次 //DataReceiveFunction(); //MessageBox.Show("串口出错!"); } } else { MessageBox.Show("串口意外关闭!"); } } public static string ReverseD(string text) { return new string(text.ToCharArray().Reverse().ToArray()); } public static void RequestSensor(string Number) { try { int number = int.Parse(Number); char state; state = oldStr[number]; MqttCtrl.client_sendMsg("SZYL:"+Number + "-" + state.ToString()); } catch (Exception) { throw; } } } }
里面还有一个crc检验
using System; namespace CefSharp.MinimalExample.WinForms { public class CalcOnCrc16 { public ushort CRC16(byte[] bytes) { ushort value; ushort newLoad = 0xffff, In_value; int count = ; for (int i = ; i < bytes.Length; i++) { value = (ushort)bytes[i]; newLoad = (ushort)(Convert.ToInt32(value) ^ Convert.ToInt32(newLoad)); In_value = 0xA001; while (count < ) { if (Convert.ToInt32(newLoad) % == )//判断最低位是否为1 { newLoad -= 0x00001; newLoad = (ushort)(Convert.ToInt32(newLoad) / );//右移一位 count++;//计数器加一 newLoad = (ushort)(Convert.ToInt32(newLoad) ^ Convert.ToInt32(In_value));//异或操作 } else { newLoad = (ushort)(Convert.ToInt32(newLoad) / );//右移一位 count++;//计数器加一 } } count = ; } return newLoad; } } }
PS:这个单片机是我请求一次,它才发回消息,不是主动的发,所以我的程序里面还有计时器循环请求状态.
下面就是发送到mqtt消息平台,首先接收
教程是这里的,如果看不懂直接看我源码
教程地址:https://help.aliyun.com/document_detail/59721.html?spm=a2c4g.11186623.6.590.666432b1pvEQrL
using System; using System.Security.Cryptography; using System.Text; using System.Windows.Forms; using uPLibrary.Networking.M2Mqtt; using uPLibrary.Networking.M2Mqtt.Messages; namespace CefSharp.MinimalExample.WinForms { public class MqttCtrl { // //实例 ID,购买后从控制台获取 //static String instanceId = " "; // //此处填写购买得到的 MQTT 接入点域名 // static String brokerUrl = " "; // //此处填写阿里云帐号 AccessKey // static String accessKey = " "; // //此处填写阿里云帐号 SecretKey // static String secretKey = ""; // //此处填写在 MQ 控制台创建的 Topic,作为 MQTT 的一级 Topic // static String parentTopic = " "; // //此处填写客户端 ClientId,需要保证全局唯一,其中前缀部分即 GroupId 需要先在 MQ 控制台创建 // static String clientId = " " + DateTime.Now.Ticks.ToString(); // static MqttClient client = new MqttClient(brokerUrl); //实例 ID,购买后从控制台获取 static String instanceId = " "; //此处填写购买得到的 MQTT 接入点域名 static String brokerUrl = " "; //此处填写阿里云帐号 AccessKey static String accessKey = " "; //此处填写阿里云帐号 SecretKey static String secretKey = ""; //此处填写在 MQ 控制台创建的 Topic,作为 MQTT 的一级 Topic static String parentTopic = "SJJK"; //此处填写客户端 ClientId,需要保证全局唯一,其中前缀部分即 GroupId 需要先在 MQ 控制台创建 static String clientId = " " + DateTime.Now.Ticks.ToString(); static MqttClient client = new MqttClient(brokerUrl); public static void Init() { client.MqttMsgPublishReceived += client_recvMsg; client.MqttMsgPublished += client_publishSuccess; client.ConnectionClosed += client_connectLose; //username和 Password 签名模式下的设置方法,参考文档 https://help.aliyun.com/document_detail/48271.html?spm=a2c4g.11186623.6.553.217831c3BSFry7 String userName = "Signature|" + accessKey + "|" + instanceId; String passWord = HMACSHA1(secretKey, clientId); client.Connect(clientId, userName, passWord, true, ); //订阅 Topic,支持多个 Topic,以及多级 Topic //string[] subTopicArray = { parentTopic + "/SamJan", parentTopic + "/subDemo2/level3" }; string[] subTopicArray = { parentTopic + "/SamJan", parentTopic + "/SensorState" }; //string[] subTopicArray = { parentTopic + "/SensorState" }; byte[] qosLevels = { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE }; //订阅 client.Subscribe(subTopicArray, qosLevels); //client.Publish(parentTopic + "/SamJan", Encoding.UTF8.GetBytes("hello mqtt,尚哲智能"), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false); //发送 P2P 消息,二级 topic 必须是 p2p,三级 topic 是接收客户端的 clientId //client.Publish(parentTopic + "/p2p/" + clientId, Encoding.UTF8.GetBytes("(P2P) hello mqtt"), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false); //System.Threading.Thread.Sleep(10000); //client.Disconnect(); } // public static void client_sendMsg(string msg) { client.Publish(parentTopic + "/SamJan", Encoding.UTF8.GetBytes(msg), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false); } static void client_sendMsgByP2P(string msg) { client.Publish(parentTopic + "/p2p/" + clientId, Encoding.UTF8.GetBytes(msg), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false); } static void client_disConnect() { client.Disconnect(); } static void client_recvMsg(object sender, MqttMsgPublishEventArgs e) { // access data bytes throug e.Message //MessageBox.Show("Recv Msg : Topic is " + e.Topic + " ,Body is " + Encoding.UTF8.GetString(e.Message)); if (e.Topic == "SJJK/SensorState") { COMCtrl.RequestSensor(Encoding.UTF8.GetString(e.Message)); } } static void client_publishSuccess(object sender, MqttMsgPublishedEventArgs e) { // access data bytes throug e.Message Console.WriteLine("Publish Msg Success"); } static void client_connectLose(object sender, EventArgs e) { // access data bytes throug e.Message Console.WriteLine("Connect Lost,Try Reconnect"); Init(); } public static string HMACSHA1(string key, string dataToSign) { Byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(key); HMACSHA1 hmac = new HMACSHA1(secretBytes); Byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(dataToSign); Byte[] calcHash = hmac.ComputeHash(dataBytes); String calcHashString = Convert.ToBase64String(calcHash); return calcHashString; } } }
官方Demo: https://code.aliyun.com/aliware_mqtt/mqtt-demo/tree/master?spm=a2c4g.11186623.2.38.4181775ewvOQVo
与前端妹子沟通好,你们就可以愉快的吵架了.
…END…
引言 当你用招行的卡在招行取款机取钱的时候 当你用招行的卡在工行取款机取钱的...
连接计算机内核和交互界面的桥梁叫做终端,在下面这样黑乎乎的窗口敲代码才有高...
小明是一位普通市民。 每天,小明和邻居们一样,将生活垃圾混在一起,扔到小区的...
本文转载自微信公众号「小林coding」,作者小林coding。转载本文请联系小林codin...
蒋彪,腾讯云高级工程师,10+年专注于操作系统相关技术,Linux内核资深发烧友。...
大多数组织无法完全了解用户在云计算环境中可以做什么。他们不知道谁可以假冒其...
当我们有时候登录服务器windows2008时有时候会出现: 远程桌面 服务当前正忙,因...
一、5G消息概述 中国电信、中国移动、中国联通于2020年4月8日共同发布《5G消息白...
为什么要安装VMTools? VMTools是为 弹性云服务器 提供高性能磁盘和网卡的半虚拟...
背景介绍 ? ? ? ? 为了摸底项目的性能,需要进行性能测试。经过一番调研之后,决...