目录
引入
GUI整改
client添加GPS分析
完善服务器网络通讯部分代码
添加GPS的BSW层
GPS操作部分代码(相当于驱动)
效果展示
项目管理操作
引入
最近在写论文加上出去玩了一圈所以停更了一段时间。上次咱们GPS有个室内用不了的问题,咱们看看咋解决一下。
GUI整改
'''
fuction : 客户端界面
author : 辛天宇
date : 2024-4-12
-------------------------------
author date modify
辛天宇 2024-4-12 引入大小控制全局设置功能
'''
import PySimpleGUI as sg
import tool
import global_var
# 调用显示框架
def show_window(theme):
# 是否使用自定义标题栏
use_custom_titlebar = False
# 设置主题
sg.theme(theme)
# 创建菜单
Menu = sg.Menu
# 左部layout
layout_l = [
[
tool.name('NetWork'),
sg.Button('Connect', key='Connect', font=global_var.GLOBAL_FONT)
],
[
tool.name('NetWork'),
sg.Button('Disconnect', key='Disconnect', font=global_var.GLOBAL_FONT)
],
[
tool.name('NetWork'),
sg.Output(size=(32, 1), key='IP', font=global_var.GLOBAL_FONT)
],
[
sg.Checkbox('Input', use_custom_titlebar, enable_events=True, key='input', font=global_var.GLOBAL_FONT)
],
[
sg.InputText(disabled=True, key='txbuff', font=global_var.GLOBAL_FONT),
sg.Button('SEND', key='send', font=global_var.GLOBAL_FONT)
],
[
sg.Slider(range=(0, 100), orientation='h', size=(57, 40), default_value=0, key='DAC', enable_events=True, font=global_var.GLOBAL_FONT),
sg.Text('DAC', size=(5,2), justification='c',pad=(0,(20,0)), font=global_var.GLOBAL_FONT)
],
[
sg.InputText(key='AT24C02_I', default_text='', font=global_var.GLOBAL_FONT),
sg.Button('AT24C02 WRITE', key='AT24C02_W', font=global_var.GLOBAL_FONT)
],
]
# 右部layout
layout_r = [
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='LED_O', font=global_var.GLOBAL_FONT),
sg.Button('LED', key='LED', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='SR501_O', font=global_var.GLOBAL_FONT),
sg.Button('SR501', key='SR501', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='SR04_O', font=global_var.GLOBAL_FONT),
sg.Button('SR04', key='SR04', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='IRDA_O', font=global_var.GLOBAL_FONT),
sg.Button('IRDA', key='IRDA', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='DHT11_O', font=global_var.GLOBAL_FONT),
sg.Button('DHT11', key='dht11', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='DS18B20_O', font=global_var.GLOBAL_FONT),
sg.Button('DS18B20', key='ds18b20', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='GPS_O', font=global_var.GLOBAL_FONT),
sg.Button('DIRECT', key='GPS_direct', font=global_var.GLOBAL_FONT),
sg.Button('MEMORY', key='GPS_memory', font=global_var.GLOBAL_FONT)
],
[
sg.Output(size=(global_var.OUTPUT_X, global_var.OUTPUT_Y), key='AT24C02_O', font=global_var.GLOBAL_FONT),
sg.Button('AT24C02 READ', key='AT24C02_R', font=global_var.GLOBAL_FONT)
],
#[tool.name('Text'), sg.Button('IIC', key='IIC')],
]
# 修饰
topic = tool.add_stars_to_string(global_var.TOPIC, 10)
# 整体layout
layout = [
[sg.T(topic, text_color='blue', justification='c', font=global_var.topic_font)],
[sg.Col(layout_l), sg.Col(layout_r)],
[sg.Text('Output:', size=(7,1), justification='r',pad=(0,0), font=global_var.GLOBAL_FONT),],
[sg.Output(size=(120, 16), key='Output', font=global_var.GLOBAL_FONT)],
[sg.Button('Clean', key='Clean'), sg.Button('Quit', key='Quit')]
]
window = sg.Window('The PySimpleGUI Element List', layout, finalize=True, keep_on_top=True)
return window
# 处理事件
def event_handle():
window = show_window('DefaultNoMoreNagging')
# 事件循环
while True:
try:
event, values = window.read()
if event == 'Exit':
break
if event == 'dht11':
message = f"{global_var.TEM}°C {global_var.HUM}%"
window['Getvalue'].update(message)
if event == 'ds18b20':
message = f"{global_var.TEM}°C"
window['Getvalue'].update(message)
if event == 'input':
print(f"INPUT-----------------")
elif event == 'Quit':
print(f"See you.............")
break
# elif event == 'Connect':
# global_var.SERVER_IP = "192.168.5.10"
# window['IP'].update(global_var.SERVER_IP)
# elif event == 'Disconnect':
# global_var.SERVER_IP = "connectionless network service"
# window['IP'].update(global_var.SERVER_IP)
elif event is None:
print(f"xxxxxxxxxxxxxxxxxxxx")
break
elif event == 'LED':
print(f"LED-----------------")
# 处理其他事件...
except Exception as e:
window.close()
print(f"An error occurred: {e}")
return 0
window.close()
return 0
def main():
# theme参考/client/README
event_handle()
if __name__ == '__main__':
main()
之前给老师看了下ui,老师说字太小了所以这次我优化了一下可以通过全局变量控制。
这次够大了吧
这里可以控制大小设定了
client添加GPS分析
接收到的数据只有成功和失败两种,但是发送的话我设置了两种模式direct和memory。
direct: 这种模式是直接启动GPS读取实际的数据,但是我们室内肯定用不了GPS哇。于是就加个读取存储器的默认值。
memory:这个模式就是直接读取存储器的默认值
GPS的命令不多所以两种模式共用一个设备号
完善服务器网络通讯部分代码
这块就比较简单了,基本和以前的没啥区别。后面这里要整合一下抽象出一个函数来。可以缩小代码体积。
添加GPS的BSW层
/*
* func : Handle dac Settings
* return : error code
* input : <cmd> (GPS cmd)
* output :<data> (longitude and latitude)
* author date modify
--------------------------------
xintianyu 2024-5-11 create
*/
int gps_handle(GPS_CMD cmd, char *data)
{
char *device = "/dev/ttymxc5";
int fd;
int iRet;
char *memory = usth;
char buf[1000];
char time[100];
char Lat[100];
char ns[100];
char Lng[100];
char ew[100];
float fLat, fLng;
/* 1. open */
/* 2. setup
* 115200,8N1
* RAW mode
* return data immediately
*/
/* 3. write and read */
if (cmd_direct == cmd)
{
fd = open_port(device);
if (fd < 0)
{
printf("open %s err!\n", device);
return -1;
}
iRet = set_uart(fd, 9600, 8, 'N', 1);
if (iRet)
{
printf("set port err!\n");
return iRet;
}
/* eg. $GPGGA,082559.00,4005.22599,N,11632.58234,E,1,04,3.08,14.6,M,-5.6,M,,*76"<CR><LF>*/
/* read line */
iRet = read_gps_raw_data(fd, buf);
/* parse line */
if (iRet == 0)
{
iRet = parse_gps_raw_data(buf, time, Lat, ns, Lng, ew);
}
/* printf */
if (iRet == 0)
{
printf("Time : %s\n", time);
printf("ns : %s\n", ns);
printf("ew : %s\n", ew);
printf("Lat : %s\n", Lat);
printf("Lng : %s\n", Lng);
/* 纬度格式: ddmm.mmmm */
sscanf(Lat+2, "%f", &fLat);
fLat = fLat / 60;
fLat += (Lat[0] - '0')*10 + (Lat[1] - '0');
/* 经度格式: dddmm.mmmm */
sscanf(Lng+3, "%f", &fLng);
fLng = fLng / 60;
fLng += (Lng[0] - '0')*100 + (Lng[1] - '0')*10 + (Lng[2] - '0');
printf("Lng,Lat: %.06f,%.06f\n", fLng, fLat);
sprintf(data,"@009s%s%s", Lng, Lat);
}
else
{
sprintf(data,"@009e");
}
}
else if(cmd_memory == cmd)
{
sprintf(data,"@009s%s", memory);
}
else
{
sprintf(data,"@009e");
}
return 0;
}
大部分内容沿用了韦东山老师的代码,在外层封装了个任务判断而已。
GPS操作部分代码(相当于驱动)
/*
* func : set uart
* return : err code
* input : <fd> (uart device) <Speed> (speed) <Bits> (bits) <Event> (event) <Stop> (stop bit)
* output :NULL
* author date modify
--------------------------------
weidongshan 2024-5-11 create
*/
int set_uart(int fd, int Speed, int Bits, char Event, int Stop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
newtio.c_oflag &= ~OPOST; /*Output*/
switch( Bits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( Event )
{
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
switch( Speed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( Stop == 1 )
newtio.c_cflag &= ~CSTOPB;
else if ( Stop == 2 )
newtio.c_cflag |= CSTOPB;
newtio.c_cc[VMIN] = 1; /* 读数据时的最小字节数: 没读到这些数据我就不返回! */
newtio.c_cc[VTIME] = 0; /* 等待第1个数据的时间:
* 比如VMIN设为10表示至少读到10个数据才返回,
* 但是没有数据总不能一直等吧? 可以设置VTIME(单位是10秒)
* 假设VTIME=1,表示:
* 10秒内一个数据都没有的话就返回
* 如果10秒内至少读到了1个字节,那就继续等待,完全读到VMIN个数据再返回
*/
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
//printf("set done!\n");
return 0;
}
/*
* func : set uart
* return : err code
* input : <com> (uart id)
* output :NULL
* author date modify
--------------------------------
weidongshan 2024-5-11 create
*/
int open_port(char *com)
{
int fd;
//fd = open(com, O_RDWR|O_NOCTTY|O_NDELAY);
fd = open(com, O_RDWR|O_NOCTTY);
if (-1 == fd)
{
return(-1);
}
if(fcntl(fd, F_SETFL, 0)<0) /* 设置串口为阻塞状态*/
{
printf("fcntl failed!\n");
return -1;
}
return fd;
}
/*
* func : read gps values
* return : err code
* input : <fd> (device id) <buf> (values)
* output :NULL
* author date modify
--------------------------------
weidongshan 2024-5-11 create
*/
int read_gps_raw_data(int fd, char *buf)
{
int i = 0;
int iRet;
char c;
int start = 0;
while (1)
{
iRet = read(fd, &c, 1);
if (iRet == 1)
{
if (c == '$')
start = 1;
if (start)
{
buf[i++] = c;
}
if (c == '\n' || c == '\r')
return 0;
}
else
{
return -1;
}
}
}
/*
* func : gps values handle
* return : err code
* input : <buf> (values) <time> (time) <ns> (Northern and southern hemispheres) <ew> (Eastern and western hemispheres)
* : <lat> (latitude) <lng> (longitude)
* output :NULL
* author date modify
--------------------------------
weidongshan 2024-5-11 create
*/
/* eg. $GPGGA,082559.00,4005.22599,N,11632.58234,E,1,04,3.08,14.6,M,-5.6,M,,*76"<CR><LF> */
int parse_gps_raw_data(char *buf, char *time, char *lat, char *ns, char *lng, char *ew)
{
char tmp[10];
if (buf[0] != '$')
return -1;
else if (strncmp(buf+3, "GGA", 3) != 0)
return -1;
else if (strstr(buf, ",,,,,"))
{
printf("Place the GPS to open area\n");
return -1;
}
else {
//printf("raw data: %s\n", buf);
sscanf(buf, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,]", tmp, time, lat, ns, lng, ew);
return 0;
}
}
我直接拿韦东山老师的代码过来用了,这些代码都比较简单,就是打开串口设置串口读取数据和数据处理。严格来说韦东山老师也是仿照linux源码的驱动程序写的。在国外引用思想也要表明。但是国内版权意识比较差这里也没要求。如果严格实施的话估计全世界都成为GPL的天下了哈哈。