STM32开发GPRS传输的GPS定位器 C#编写服务器转发程序,客户端显示轨迹_c# gps系统

26 阅读4分钟

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。 img img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

						{
							gps_flag=1;
							
						}
						else
						{
							gps_n=0;
							gps_e=0;
							break;
						} 
				}	
				if(gps_flag==1)
				{
					if((count==3)&&(gpsdata[i+1]!=','))
					{
						gps_n=((gpsdata[i+1]-0x30)*100000+(gpsdata[i+2]-0x30)*10000+((gpsdata[i+3]-0x30)*100000+(gpsdata[i+4]-0x30)*10000+(gpsdata[i+6]-0x30)*1000+(gpsdata[i+7]-0x30)*100+(gpsdata[i+8]-0x30)*10+(gpsdata[i+9]-0x30))/60);
					}
					if((count==5)&&(gpsdata[i+1]!=','))
					{
						gps_e=((gpsdata[i+1]-0x30)*1000000+(gpsdata[i+2]-0x30)*100000+(gpsdata[i+3]-0x30)*10000+((gpsdata[i+4]-0x30)*100000+(gpsdata[i+5]-0x30)*10000+(gpsdata[i+7]-0x30)*1000+(gpsdata[i+8]-0x30)*100+(gpsdata[i+9]-0x30)*10+(gpsdata[i+10]-0x30))/60);			
					}		
					if(count>=13)
					{
						count=0;
						gps_flag=0;
						break;
					}
				}	
			}	
		}
	}
	memset(U2_RX_data,0, 1024);		
	DMA1_Channel6->CNDTR = 1024;                            //??????????           
	DMA_Cmd(DMA1_Channel6,ENABLE);                       //??DMA             
}

单片机与服务器通过AT指令控制GPRS模块与服务器通信,AT指令是比较难的,开发过的会有感受,AT指令返回的状态比较多,并不是返回一种或两种结果。不但要按照正常流程一步一步发送AT指令,还要有错误返回处理。AT指令挺复杂的,特别适合用状态机处理这些流程。



switch (M26_info.state)
{ case GPRS_state_Poweroff : if(AT_Delay_Timer>5) { GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET); GPIO_SetBits(GPIOA,GPIO_Pin_1); GPIO_ResetBits(GPIOA, GPIO_Pin_7); GPIO_ResetBits(GPIOA, GPIO_Pin_4); // Sleep } if(AT_Delay_Timer>25) { GPIO_ResetBits(GPIOA,GPIO_Pin_1); GPIO_SetBits(GPIOA, GPIO_Pin_7); } if(AT_Delay_Timer>45) { GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET); M26_info.state=GPRS_state_AT; AT_Timeslimite=0; AT_Delay_Timer=0; AT_overtime=0; ZC_DATA_flog=1; } break; case GPRS_state_AT : M26_ATTR(5,30,50,"AT+IPR=115200&W\r\n","OK","","","","",GPRS_state_CREG,GPRS_state_AT); break; case GPRS_state_CREG : M26_ATTR(5,30,100,"AT+CREG?\r\n","+CREG: 0,1","+CREG: 0,5","+CREG: 0,2","+CREG: 0,3","+CREG: 0,4",GPRS_state_CSQ,GPRS_state_CREG); break; case GPRS_state_CSQ : M26_ATTR(2,30,20,"AT+CSQ\r\n","+CSQ:","","","","",GPRS_state_QIDNSIP,GPRS_state_CSQ); case GPRS_state_QIDNSIP: M26_ATTR(2,30,5,"AT+QIFGCNT=0\r\n","OK","","","","",GPRS_state_QIDEACT,GPRS_state_Poweroff); break; case GPRS_state_QIDEACT: M26_ATTR(2,2,50,"AT+QICSGP=1,"CMMTM"\r\n","OK","","ERROR","","",GPRS_state_QIREGAPP,GPRS_state_Poweroff); break; case GPRS_state_QIREGAPP: M26_ATTR(2,2,50,"AT+QIREGAPP\r\n","OK","","ERROR","","",GPRS_state_QIACT,GPRS_state_Poweroff); break; case GPRS_state_QIACT: M26_ATTR(10,2,300,"AT+QIACT\r\n","OK","","ERROR","","",GPRS_state_QIOPEN,GPRS_state_Poweroff); break; case GPRS_state_QIOPEN: M26_ATTR(20,10,50,"AT+QIOPEN="TCP","122.51.33.246","8888"\r\n","CONNECT OK","ALREADY CONNECT","ERROR","CONNECT FAIL","",GPRS_state_QISEND,GPRS_state_QIACT); break; case GPRS_state_QISTAT: M26_ATTR(10,10,500,"AT+QISTAT\r\n","STATE: CONNECT OK","","STATE: IP INITIAL","","",GPRS_state_QISEND,GPRS_state_QIOPEN); break; case GPRS_state_QISEND: GPRS_DATA_flog=1; M26_ATTR(50,20,100,"AT+QISEND=27\r\n",">",">","ERROR","ERROR","ERROR",GPRS_state_QISENDDATA,GPRS_state_QISENDDATA); break; case GPRS_state_QISENDDATA: M26_senddata(10,10,100,"12345678","SEND OK","","ERROR","ERROR","ERROR",GPRS_state_QISEND,GPRS_state_Poweroff); break;

	default:  ; 
}

服务器后台


用C#编写服务器后台程序,他负责接收所有设备发来数据,把与客户端有关的设备数据转发给客户端。这样局域网里的客户端可以通过网关获取服务器的数据。服务器程序用到多线程技术,可以同时处理多个设备发来的数据。用到了Dictionary数据类型,实现设备ID与socket对应,关键代码如下



private void ReceiveClient(object obj) { Socket _ClientSocket = (Socket)obj; while (true) { try { byte[] result = new byte[1024]; int receiveLength = _ClientSocket.Receive(result);
string clientMessage = Encoding.UTF8.GetString(result, 0, receiveLength); string Destination_Address; string Data_Rcve; if (receiveLength == 0) { ClientSocketDictionary.Remove(_ClientSocket); _ClientSocket.Shutdown(SocketShutdown.Both); _ClientSocket.Close(); SetText2box(); break; } else { if ((result[0] == '') && (result[1] == '2'))//发送数据 目的地址 { Destination_Address = clientMessage.Substring(2, 10); Data_Rcve = clientMessage.Substring(12, clientMessage.Length-12); temp = DateTime.Now.ToString()+ " Dest is : " + Destination_Address + " Data is : " + Data_Rcve; SetTextbox(); SendMessage(clientMessage); } if ((result[0] == '') && (result[1] == '1'))//注册ID 源地址 { if (!ClientSocketDictionary.ContainsKey(_ClientSocket)) { ClientSocketDictionary.Add(_ClientSocket, clientMessage.Substring(2, 10)); SetText2box(); } else { ClientSocketDictionary.Remove(_ClientSocket); ClientSocketDictionary.Add(_ClientSocket, clientMessage.Substring(2, 10)); SetText2box(); }   
} }

            }
            catch (Exception e)
            {
                ClientSocketDictionary.Remove(_ClientSocket);
                _ClientSocket.Shutdown(SocketShutdown.Both);
                _ClientSocket.Close();
                SetText2box();
                SetText3box(e);

                break;
            }
        }
    }

public void SendMessage(string msg) { if (msg == string.Empty || this.ClientSocketDictionary.Count <= 0) return; string Destination_Address = msg.Substring(2, 10); string Data_Rcve = msg.Substring(12, msg.Length-12); msg = "$3" + Destination_Address + Data_Rcve;

        try
        {
            foreach (KeyValuePair<Socket, string> kvp in ClientSocketDictionary)
            {
               if(kvp.Value.Substring(0,10)== Destination_Address)
               {
                   kvp.Key.Send(Encoding.UTF8.GetBytes(msg));
               }              
            }
        }
        catch (Exception e)
        {
            SetText3box(e);
        }
    }      

客户端


C#编写客户端程序,调用百度地图API,实现地图打标,绘制轨迹。客户端工作流程是这样的,首先向服务器发送注册自身ID,然后向服务器获取相关设备ID的数据,解析数据,调用百度地图API实现打标定位等。关键代码如下



private void button1_Click(object sender, EventArgs e) { try { clientScoket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientScoket.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text.ToString()), 8888)); t = new Thread(ReceiveMessage);//开启线程执行循环接收消息 t.IsBackground=true; t.Start(); button1.Text = "已连接服务器"; button1.Enabled = false; } catch (Exception ex) { SetText3box(ex); button1.Text = "无法连接服务器"; button1.Enabled = true; }

    }
   
    public delegate void CallSetTextbox(string ms);
    void ReceiveMessage()//接收消息
    {
        
        string Destination_Address;
        string Data_Rcve;
        send_flog = 1;
        while (true)
        {
            if (clientScoket.Connected == true)
            {
                
                
                    if (send_flog == 1)
                    {
                        send_flog = 0;
                        message = "$1" + textBox4.Text;
                        SendMessage(message);
                    }
                    int length = 0;

                    try
                    {
                        length = clientScoket.Receive(data);
                     }
                    catch (Exception e)
                    {

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。 img img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!