【问题标题】:SQL update using data collected by C# from Arduino Serial使用 C# 从 Arduino Serial 收集的数据进行 SQL 更新
【发布时间】:2012-06-20 19:24:33
【问题描述】:

我正在尝试用 C# 编写一个简单的程序,该程序将读取通过串行连接的 Arduino 输出的数据,将相关数据从文本字符串中提取出来,这些文本字符串经过格式化以便在串行监视器中易于理解,显示两个只读文本框中的两条信息,充当计数器(每次更新信息时覆盖),并使用这些数字更新 SQL 表。


例子:

Arduino 输出:

'Day Users: 234231'
'All Users: 433241'

C# 在 textbox1 中显示完整的消息

C# 在 textbox2 中显示 234231

C# 在 textbox3 中显示 433241

C# UPDATES SQL 表类似于:

SqlCommand myCommand = new SqlCommand("UPDATE USER_NUMBERS
SET NUMBERZ= 234231 
WHERE UPTIME = DAYHK");

但显然,'234231' 是一个变量,由 Arduino 的输入指定,然后通知 textbox2 的内容和更新 SQL 表所需的值。


我对 C# 很陌生,但到目前为止,我有一个程序可以从 Arduino 读取串行数据并将整个输出放入 textbox1,但仅此而已。

如何指定我想要分配给值的传入数据的一部分作为 textbox2(或 textbox3)中的文本输出,然后使用它来执行此操作并更新我保存的值SQL 表?

到目前为止我的代码是这样的:

    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;

namespace Serial_Reader
{
    public partial class Form1 : Form
    {

        string RxString;

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = "COM3";
            serialPort1.BaudRate = 9600;

            serialPort1.Open();
            if (serialPort1.IsOpen)
            {
                buttonStart.Enabled = false;
                buttonStop.Enabled = true;
                buttonSQL.Enabled = true;
                textBox1.ReadOnly = false;
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
                buttonStart.Enabled = true;
                buttonStop.Enabled = false;
                buttonSQL.Enabled = false;
                textBox1.ReadOnly = true;
            }
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            // If the port is closed, don't try to send a character.

            if (!serialPort1.IsOpen) return;

            // If the port is Open, declare a char[] array with one element.
            char[] buff = new char[1];

            // Load element 0 with the key character.

            buff[0] = e.KeyChar;

            // Send the one character buffer.
            serialPort1.Write(buff, 0, 1);

            // Set the KeyPress event as handled so the character won't
            // display locally. If you want it to display, omit the next line.
            e.Handled = true;
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            RxString = serialPort1.ReadExisting();
            this.Invoke(new EventHandler(DisplayText));
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen) serialPort1.Close();
        }

        private void DisplayText(object sender, EventArgs e)
        {
            textBox1.AppendText(RxString);
        }

        private void buttonSQL_Click(object sender, EventArgs e)
        {

        }

    }
 }

正如您从“我的”专家评论中看到的,但编程无能,我正在使用出色教程 here 中的代码:而我的程序将有一个额外的按钮来开始 SQL 通信,当串行通讯已停止,并出现两个额外的文本框。


编辑

输入格式为:

Someone got up from seat number 9
All-time users on seat number 9 is: 5
Today's total users: 17
All-time total users: 17

这样检查串行监视器的非程序员可以很容易地理解输出。第一行总是“有人起床”或“有人坐下”,在第二行,只有数字发生变化,第三行和第四行也是如此,但第三和第四行的数字(在这种情况相同,因为系统运行不到一天)是需要解析的。


编辑 2(新代码):

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.Data.SqlClient;

namespace Serial_Reader
{
    public partial class Form1 : Form
    {

        string RxString;

        public Form1()
        {
              InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = "COM3";
            serialPort1.BaudRate = 9600;

            serialPort1.Open();
            if (serialPort1.IsOpen)
            {
                buttonStart.Enabled = false;
                buttonStop.Enabled = true;
                buttonSQL.Enabled = true;
                textBox1.ReadOnly = true;
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
                buttonStart.Enabled = true;
                buttonStop.Enabled = false;
                buttonSQL.Enabled = false;
                textBox1.ReadOnly = true;
            }
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            // If the port is closed, don't try to send a character.

            if (!serialPort1.IsOpen) return;

            // If the port is Open, declare a char[] array with one element.
            char[] buff = new char[1];

            // Load element 0 with the key character.

            buff[0] = e.KeyChar;

            // Send the one character buffer.
            serialPort1.Write(buff, 0, 1);

            // Set the KeyPress event as handled so the character won't
            // display locally. If you want it to display, omit the next line.
            e.Handled = true;
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            RxString = serialPort1.ReadExisting();
            this.Invoke(new EventHandler(DisplayText));


        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen) serialPort1.Close();
        }

        private void DisplayText(object sender, EventArgs e)
        {
            textBox1.AppendText(RxString);

        }

        private void buttonSQL_Click(object sender, EventArgs e)
        {
            //   SqlConnection myConnection = new SqlConnection("user id=username;" +
            //                            "password=password;server=serverurl;" +
            //                            "Trusted_Connection=yes;" +
            //                            "database=database; " +
            //                            "connection timeout=30");

            do
            {
                string dayUsers, allUsers;
                string s1 = "Today's total users: ";
                string s2 = "All-time total users: ";

                if (RxString.Contains(s1))
                {
                dayUsers = RxString.Replace(s1, "");
                textDU.Text = dayUsers;
           //     string queryDay = "UPDATE USER_NUMBERS SET NUMBERZ=" + dayUsers + "WHERE UPTIME=DAYHK";
                }

                if (RxString.Contains(s2))
                {
                allUsers = RxString.Replace(s2, "");
                textAU.Text = allUsers;
           //     string queryAll = "UPDATE USER_NUMBERS SET NUMBERZ=" + allUsers + "WHERE UPTIME=ALLHK";
                }
            }
            while (serialPort1.IsOpen);
        }



        private void textDU_TextChanged(object sender, EventArgs e)
        {

        }

        private void textAU_TextChanged(object sender, EventArgs e)
        {

        }

    }
}

EDIT 3(传入数据):

if (abs (then [i] - now[i]) > THRESH)
{
  Serial.print ("Someone ");
  if (now [i] > then [i])
  {
    Serial.print ("sat on");
    allusers++;
    dayusers++;
    digitalWrite(counterPin, HIGH);  // hit counter
    delay(75);
    digitalWrite(counterPin, LOW);
    val[i]++;
  }  
  else
  {
    Serial.print ("got up from");
  }  
  Serial.print (" seat number ");
  Serial.println (i);
  Serial.print ("All-time users on seat number ");
  Serial.print (i);
  Serial.print (" is: ");
  Serial.println (val[i]); 
  Serial.print ("Today's total users: ");
  Serial.println (dayusers);
  Serial.print ("All-time total users: ");
  Serial.println (allusers);
}

【问题讨论】:

    标签: c# sql serial-port arduino visual-studio-2012


    【解决方案1】:

    如果您知道输入字符串始终采用相同的格式,并且数字始终为 6 位,您可以使用简单的子字符串:

    int dayUsers, allUsers;
    Int32.TryParse(RxString.Substring(12, 6), out dayUsers);
    Int32.TryParse(RxString.Substring(32, 6), out allUsers);
    

    否则你可以让解析更复杂一点:

    int dayUsers, allUsers;
    string[] parts = RxString.Split('\'', ':');
    if (parts.Length > 5)
    {
        Int32.TryParse(parts[2].Trim(), out dayUsers);
        Int32.TryParse(parts[5].Trim(), out allUsers);
    }
    

    那么就只需要使用文本框中的数字和SQL查询即可:

    textBox2.Text = dayUsers.ToString();
    textBox3.Text = allUsers.ToString();
    
    string query = "UPDATE USER_NUMBERS SET NUMBERZ=" + dayUsers + "WHERE UPTIME=DAYHK"
    

    编辑: 鉴于 textBox1 中有四行数据,您可以使用类似这样的方法来提取包含数字的字符串:

    string[] inputLines = textBox1.Text.Split('\n');
    if (inputLines.Length == 4)
    {
        string dayUsers = inputLines[2].Substring(inputLines[2].IndexOf(':') + 1).Trim();
        string allUsers = inputLines[3].Substring(inputLines[3].IndexOf(':') + 1).Trim();
    }
    

    编辑 2: TextBox1中可能不完整数据的代码解析建议:

    private void buttonSQL_Click(object sender, EventArgs e)
    {
        // Get unsaved input from text box
        string input = textBox1.Text;
        string[] inputLines = input.Split('\n');
    
        // Find and process relevant input
        foreach(string line in inputLines)
        {
            if (line.EndsWith("\r")) // Make sure line is complete
            {
                if (line.StartsWith("Today's total users: "))
                {
                    string dayUsers = line.Substring(20).Trim();
                    textDU.Text = dayUsers;
                    // SQL query...
                }
                else if (line.StartsWith("All-time total users: "))
                {
                    string allUsers = line.Substring(21).Trim();
                    textAU.Text = allUsers;
                    // SQL query...
                }
            }
        }
    
        // Only keep unparsed text in text box
        textBox1.Text = inputLines[inputLines.Length - 1];
    }
    

    【讨论】:

    • 您好,感谢您的快速回复。我已经编辑了原始帖子以解释一些关于传入数据的信息。查看您的代码并在发布后阅读了一些有关 Int32.TryParse 的信息,这似乎很有意义,如果您不介意,我只需要一些关于细节的帮助吗?你从哪里得到数字 2 和 5?输入的数字并不总是六位数字,但它们永远不会超过六位数字......
    • 您好,2 和 5 来自假设输入格式为:“'Day Users: 234231'\n'All Users: 433241'”。用字符 ' 和 : 拆分该字符串将创建 7 个部分,其中第三和第六部分(从零开始的索引 2 和 5)将包含数字,请参阅 String.Split() 和 String.Trim() 的文档。鉴于新信息,首先使用RxString.Split('\n') 将字符串分成几行,然后分别拆分第3 行和第4 行以获得第二部分中的数字可能是最干净的:part[2].Split(':')part[3].Split(':')
    • 再次您好,谢谢您,我尝试了拆分和修剪,但我无法让它工作 - 使用拆分时,您是否留下两个字符串,一个两边性格?我编辑了原始帖子以保存我想出的代码的可怕格式......这仍然不起作用。使用Split('\n') 时,我收到了一个错误,因为数组中没有足够的parts,据说,它是否以某种方式无法正确解释换行符?达到字符数限制>>
    • (续) 上面的代码使用ContainsReplace 来选择和修剪RxString 的右侧部分并分配它,但现在它只是挂着NullReferenceException。是我的语法错了吗?
    • 你从哪里得到 NullReferenceException?我现在能看到的唯一空候选是 RxString、textAU、textDU 和 serialPort1。鉴于已收到任何文本,它们都不应该为空。检查异常中的行号或调用堆栈。 Split('\n') 在换行符处拆分字符串。我假设总是同时收到所有四行,但这可能不是真的。当按下 SQL 按钮时,最好使用 textBox1 的内容而不是 RxString,然后将 Split 等应用于该字符串。我将编辑我的回复以澄清。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多