025——从GUI->Client->Server->driver实现对LED的控制

目录

1、添加服务器中对客户端数据的具体分设备处理

2、实现将数组中的某些位数据转化为整型

3、修改client和server,互相可处理LED

4、结合驱动程序实现对物理设备的控制

4.1 增加驱动处理句柄

4.2 连接驱动处理句柄和tcp通讯接口

4.3 在client端做对应处理

4.4 成果展示

5、客户端添加对退出的处理


1、添加服务器中对客户端数据的具体分设备处理

#include "tcp.h"
#include "net.h"
#include "global.h"
#include "tool.h"
/*
*author : xintianyu
*return : err num
*data   : 2024-4-10
-----------------------
*author : ???
*return : ???
*data   : ???
*/
int usage(int argc, char *argv[])
{ if (argc != 3){  printf("Usage: %s <ip_address> <port>\n", argv[0]);  return ERROR;  }else{return NOERROR;}
}void do_nothing()
{/*void*/
}/*
*author : xintianyu
*return : err num
*data   : 2024-4-10
-----------------------
*author : ???
*return : ???
*data   : ???
*/
int tcp_server(int argc, char *argv[]) 
{int server_fd, client_fd;  struct sockaddr_in server_addr, client_addr;  socklen_t client_len = sizeof(client_addr); char *ip_address = argv[1];  int port = atoi(argv[2]);  // 创建TCP套接字  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  perror("socket creation failed");  exit(EXIT_FAILURE);  }  /*支持快速重新绑定*/int b_reuse = 1;setsockopt (server_fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));// 设置服务器地址信息  memset(&server_addr, 0, sizeof(server_addr));  server_addr.sin_family = AF_INET;  server_addr.sin_addr.s_addr = inet_addr(ip_address);  server_addr.sin_port = htons(port);  // 绑定套接字到服务器地址  if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {  perror("bind failed");  exit(EXIT_FAILURE);  }  // 监听套接字  if (listen(server_fd, 5) < 0) {  perror("listen failed");  exit(EXIT_FAILURE);  }  printf("Server listening on %s:%d...\n", ip_address, port);  //处理僵尸进程signal(SIGCHLD, SIG_IGN);// 接受客户端连接  if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) < 0) {  perror("accept failed");goto err1;}// 打印客户端信息  char client_ip[INET_ADDRSTRLEN];  inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);  printf("Client connected from %s:%d\n", client_ip, ntohs(client_addr.sin_port));if (ERROR == do_client(client_fd)){perror("client disconnect.....");goto err2;}err2:close(client_fd);
err1:close(server_fd);return NOERROR;  
}int do_client(int acceptfd)
{//MSG msg;char rx_buffer[BUFFER_SIZE];char tx_buffer[BUFFER_SIZE];int cmd;// 接收客户端消息memset(rx_buffer, 0, BUFFER_SIZE);memset(tx_buffer, 0, BUFFER_SIZE);while(1){ssize_t bytes_read = recv(acceptfd, rx_buffer, BUFFER_SIZE - 1, 0);  if (bytes_read < 0) {  perror("recv failed");  return ERROR;}else{/*确保消息以换行符结尾,并打印接收到的消息*/  if (bytes_read > 0 && rx_buffer[bytes_read - 1] != '\n') {  rx_buffer[bytes_read] = '\n';  rx_buffer[bytes_read + 1] = '\0';  }if ('Q' == rx_buffer[0] || 0 == rx_buffer[0]){printf("client quit....\n");return ERROR;}else{cmd = select_driver(rx_buffer);}printf("cmd is %d\n", cmd);
#if (STD_ON == DEBUG)printf("Received message: %s", rx_buffer);  // 回复客户端消息  //strcpy(tx_buffer, "Hello, client!\n");if (send(acceptfd, rx_buffer, strlen(rx_buffer), 0) < 0) {  perror("send failed");  }
#endif/*STD_ON == DEBUG*/}}return NOERROR;
}int select_driver(char * cmd)
{int opt = 0;MSG drv_msg;if('@' == cmd[0]){
#if (STD_ON == DEBUG)printf("cmd[0] = @\n");
#endif/*STD_ON == DEBUG*/drv_msg.device = extract_digit_number(cmd, 1, 3);/*TODO 后续需升级为多线程模式调用驱动*/switch(drv_msg.device){case 0:printf("LED!!!\n");break;case 1:printf("SR501!!!\n");break;case 2:printf("SR04!!!\n");break;case 3:printf("IRDA!!!\n");break;case 4:printf("motor!!!\n");break;case 5:printf("dht11!!!\n");break;case 6:printf("ds18b20!!!\n");break;case 7:printf("IIC!!!\n");break;case 8:printf("SPI!!!\n");break;default:printf("Unknown equipment!!!\n");}}else{printf("cmd[0] ERROR!!!\n");opt = ERROR;}opt = atoi(&cmd[1]);return opt;
}

2、实现将数组中的某些位数据转化为整型

/*
*author   : xintianyu
*function : main
*data     : 2024-4-10
-----------------------
*author : ???
*return : ???
*data   : ???
*/
int extract_digit_number(const char *str, int start_pos, const int size)
{/*有些版本的编译器规定数组下标必须为const类型*//*TODO 改为断言*/if (NULL == str || strlen(str) < start_pos + size) {  return -1;  // 字符串为空、长度不足或起始位置超出范围  }char chars[(size+1)];for (int i = 0; i < size; i++) {  chars[i] = str[start_pos + i];  }  chars[size] = '\0';  // 确保字符串正确结束  int num = 0;  for (int i = 0; i < size; i++) {  if (!isdigit(chars[i])) {  return -1;  // 包含非数字字符  }  num = num * 10 + (chars[i] - '0');  }  return num;  // 返回转换后的整型数  
}

3、修改client和server,互相可处理LED

服务器程序中我将debug关闭了改为直接由driver_select控制消息回传

客户端则是直接加上通用程序就好了

简单验证一下效果还不错

4、结合驱动程序实现对物理设备的控制

4.1 增加驱动处理句柄

/*  * 文件名: driver_handle.c  * 作者: 辛天宇  * 更新时间: 2024-04-16  * 软件版本号: 0.0.0*/
/**************************************************************
***************************INCLUDE*****************************
**************************************************************/
#include "driver_handle.h"
/**************************************************************
****************************EXTERN*****************************
**************************************************************/
/*
*author   : xintianyu
*function : Handle led Settings
*data     : 2024-4-10
-----------------------
author date  modify*/
int led_handle(DIRECTION led_direction, CMD *cmd)
{char *device = "/dev/CEBSS_led";static int fd;int ret;char buf[2];/* 打开文件 */fd = open(device, O_RDWR);if (fd == -1){printf("can not open file /dev/CEBSS_led\n");return -1;}if (direction_put == led_direction){/* write */buf[0] = strtol(device, NULL, 0);if (cmd_open == *cmd)buf[1] = 0;if (cmd_close == *cmd)buf[1] = 1;ret = write(fd, buf, 2);}else if(direction_get == led_direction){buf[0] = strtol(device, NULL, 0);ret = read(fd, buf, 2);if (ret == 2){printf("led %d status is %s\n", buf[0], buf[1] == 0 ? "on" : "off");if (buf[1] == 0){*cmd = cmd_open;}else if (buf[1] == 1){*cmd = cmd_close;}}}else{printf("Undefined command\n");}close(fd);return NOERROR;
}
#ifndef _DRIVER_HANDLE_H_
#define _DRIVER_HANDLE_H_
#include "global.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>#define LED_GPIO_0 131typedef int (*FUC_HANDLE)(void);/*TODO 很草需要完善*/
typedef enum {direction_get = 0,direction_put = 1,direction_num = 2,
}DIRECTION;typedef enum {cmd_open = 0,cmd_close = 1,cmd_get_value = 2,cmd_no = 3,cmd_num = 4,
}CMD;typedef struct {int gpio;char device_name[32];union {  DIRECTION status;} led_direction;  union {  CMD command;  } led_cmd;FUC_HANDLE handle;
} LED;typedef struct{LED led0;
}DRIVER;int led_handle(DIRECTION led_direction, CMD *cmd);#endif/*driver_handle.h*/

这里是一个对驱动控制的模板

4.2 连接驱动处理句柄和tcp通讯接口

/* TODO 传递参数后需改为使用通信结构体 */
int select_driver(char * cmd, int acceptfd)
{int opt = 0;MSG drv_msg;char *tx_buffer;DIRECTION direction;CMD drv_cmd;if('@' == cmd[0]){
#if (STD_ON == DEBUG)printf("cmd[0] = @\n");
#endif/*STD_ON == DEBUG*/drv_msg.device = extract_digit_number(cmd, 1, 3);printf("device is %d\n", drv_msg.device);/*TODO 后续需升级为多线程模式调用驱动*/switch(drv_msg.device){case 0:/*TODO 日志打印等级控制*//*TODO用设备结构体后这里要封装一下*/printf("LED!!!\n");if ('g' == cmd[4]){direction = direction_get;drv_cmd = cmd_no;led_handle(direction, &drv_cmd);if (cmd_close == drv_cmd){tx_buffer = "@000g0";}else if(cmd_open == drv_cmd){tx_buffer = "@000g1";}}else{if ('1' == cmd[5])drv_cmd = cmd_open;else if ('0' == cmd[5])drv_cmd = cmd_close;direction = direction_put;if (NOERROR == led_handle(direction, &drv_cmd)){tx_buffer = "@000p1";}else{tx_buffer = "@000p0";}}               if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0){perror("send failed");  }break;case 1:printf("SR501!!!\n");break;case 2:printf("SR04!!!\n");break;case 3:printf("IRDA!!!\n");break;case 4:printf("motor!!!\n");break;case 5:printf("dht11!!!\n");break;case 6:printf("ds18b20!!!\n");break;case 7:printf("IIC!!!\n");break;case 8:printf("SPI!!!\n");break;default:printf("Unknown equipment!!!\n");}}else{printf("cmd[0] ERROR!!!\n");opt = ERROR;}opt = atoi(&cmd[1]);return opt;
}

这里后面肯定要做相当多的优化暂时只是让他跑起来

4.3 在client端做对应处理

'''
fuction : 客户端程序
author  : 辛天宇
date    : 2024-4-13
-------------------------------
author     date      modify
辛天宇   2024-4-15   结合GUI和网络通信'''
import show
import tcp
import tool
import socket
import global_vardef send_handle(window, client_socket, values):global_var.TX_BUF = values['txbuff'] print(f"txbuff={global_var.TX_BUF}")# 清理inputwindow['txbuff'].update(value='')data = global_var.TX_BUFclient_socket.sendall(data.encode())# 接收服务器的响应data = client_socket.recv(512)# 将字节字符串转化为字符串global_var.RX_BUF = data.decode('utf-8')print(f"rx......{global_var.RX_BUF}") def quit_handel(client_socket):cmd='Q'client_socket.sendall(cmd.encode())tcp.disconnect_to_server(client_socket)# 进行一次发送和接收
def send_cmd(client_socket):data = global_var.TX_BUFclient_socket.sendall(data.encode())# 接收服务器的响应data = client_socket.recv(512)# 将字节字符串转化为字符串global_var.RX_BUF = data.decode('utf-8')# 设置发送消息
def set_tx_buf(device, message): if device == 'sr04':global_var.TX_BUF = '@002'if device == 'led':global_var.TX_BUF = '@000'+messageelif device == 'sr501':global_var.TX_BUF = '@001'elif device == 'irda':global_var.TX_BUF = '@003'elif device == 'motor':global_var.TX_BUF = '@004'+messageelif device == 'dht11':global_var.TX_BUF = '@005'+messageprint(f"dht11={global_var.TX_BUF}")elif device == 'ds18b20':global_var.TX_BUF = '@006'elif device == 'iic':global_var.TX_BUF = '@007'elif device == 'spi':global_var.TX_BUF = '@008'# 处理数据
def cmd_handle():cmd = global_var.RX_BUFif len(cmd) < 4:print("cmd ERROR")return -1if '@' == cmd[0]:# 目前驱动设备数量只有两位数if cmd[1] == '0':#LEDif cmd[2] == '0' and cmd[3] == '0':if cmd[5] == '1':print("LED Status change success")elif cmd[5] == '0':print("LED Status change failure")else:print("message ERROR")#SR501elif cmd[2] == '0' and cmd[3] == '1':if cmd[4] == '1':print("有人")elif cmd[4] == '0':print("无人")else:print("message ERROR")#SR04elif cmd[2] == '0' and cmd[3] == '2':print(cmd[4:])#irdaelif cmd[2] == '0' and cmd[3] == '3':print(cmd[4:])#motorelif cmd[2] == '0' and cmd[3] == '4':print(cmd[4:])#dht11elif cmd[2] == '0' and cmd[3] == '5':print(cmd[4:])global_var.TEM=cmd[4]+cmd[5]global_var.HUM=cmd[6]+cmd[7]#ds18b20elif cmd[2] == '0' and cmd[3] == '6':print(cmd[4:])#iicelif cmd[2] == '0' and cmd[3] == '7':print(cmd[4:])#spielif cmd[2] == '0' and cmd[3] == '8':print(cmd[4:])# 处理事件
def event_handle(window, client_socket):led = 0# 事件循环  while True:  try:cmd_handle()event, values = window.read()if event == 'input':window['txbuff'].update(disabled=not values['input'])elif event == 'send':send_handle(window, client_socket, values)elif event == 'Clean':window['Output'].update(value='')elif event == 'dht11':set_tx_buf('dht11', '2525')send_cmd(client_socket)message = f"{global_var.TEM}°C   {global_var.HUM}%"window['Getvalue'].update(message)elif event == 'ds18b20':set_tx_buf('ds18b20')send_cmd(client_socket)message = f"{global_var.TEM}°C"window['Getvalue'].update(message)elif event == 'Quit': quit_handel(client_socket) print(f"See you.............")breakelif event is None:print(f"xxxxxxxxxxxxxxxxxxxx")breakelif event == 'LED':if led % 2 == 0:set_tx_buf('led','p1')else:set_tx_buf('led','p0')led+=1if led > 100:led = 0send_cmd(client_socket)# 处理其他事件...except Exception as e:window.close()print(f"An error occurred: {e}")return 0window.close()return 0  def main():# 创建GUI对象window = show.show_window('DefaultNoMoreNagging')# 尝试连接到服务器  client_socket = tcp.connect_to_server()if client_socket is not None: event_handle(window, client_socket)if __name__ == '__main__':main()

4.4 成果展示

https://live.csdn.net/v/379386

5、客户端添加对退出的处理

def quit_handel(client_socket):cmd='Q'client_socket.sendall(cmd.encode())tcp.disconnect_to_server(client_socket)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/625031.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenStack镜像管理与制作

一、OpenStack镜像服务 1、什么是镜像 镜像通常是指一系列文件或一个磁盘驱动器的精确副本。虚拟机所使用的虚拟磁盘&#xff0c;实际上是一种特殊格式的镜像文件。云环境下尤其需要镜像。镜像就是一个模板&#xff0c;类似于VMware的虚拟机模板&#xff0c;其预先安装基本的…

Pytorch(GPU版本)简介、安装与测试运行

目录 Pytorch简介Pytorch安装查看CUDA版本Pytorch命令安装Pytorch测试运行Pytorch简介 PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序。PyTorch既可以看作加入了GPU支持的numpy,同时也可以看成一个拥有自动求导功能的强大的深度神经网络。 2…

Ctex+texmaker

最近要准备幻灯片&#xff0c;发现我喜欢的模板是用的Ctex&#xff0c;在Texlive下没有办法运行。 于是进行了很多尝试。最后找到一个快捷的办法&#xff0c;删掉自己笔记本中的texlive&#xff0c;在Ctex官网中下载Ctex套件(下载中心 – CTEX)&#xff0c;下载的版本是过时版…

初识数据库与数据库管理系统

实体的概念与数据库 实体(对象): 客观存在的事物都是实体实体数据的存储要求: 必须按照一定的分类和规律存储数据库: 专门用于存储这些实体的信息的数据集合数据库的特点: 海量存储数据&#xff0f;数据检索非常方便保持数据信息的一致&#xff0f;完整&#xff0f;并实现数据…

ubuntu22安装宝塔面板

方法一&#xff1a;运行安装宝塔命令 wget -O install.sh https://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh ed8484bec 安装成功后&#xff0c;需到服务器管理后台的安全组中配置新规则&#xff0c;放行宝塔面板的端口&#xff08;以阿…

Spark-机器学习(2)特征工程之特征提取

在之前的文章中&#xff0c;我们了解我们的机器学习&#xff0c;了解我们spark机器学习中的MLIib算法库&#xff0c;知道它大概的模型&#xff0c;熟悉并认识它。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&a…

大学生前端学习第一天:了解前端

引言&#xff1a; 哈喽&#xff0c;各位大学生们&#xff0c;大家好呀&#xff0c;在本篇博客&#xff0c;我们将引入一个新的板块学习&#xff0c;那就是前端&#xff0c;关于前端&#xff0c;GPT是这样描述的&#xff1a;前端通常指的是Web开发中用户界面的部分&#xff0c;…

C++ 使用共享内存的进程通信方式模拟生产者消费者模型

编码环境如下 系统环境&#xff1a;linux 信号量&#xff1a;使用Linux操作系统的SystemV信号量 生产者代码如下 #include <iostream> #include <sys/sem.h> #include <sys/shm.h> #include <string.h>#define SEM_KEY 0x5678 #define SHM_KEY 0xAB…

适用于 Windows 的 10 个顶级 PDF 编辑器 [免费和付费]

曾经打开PDF文件&#xff0c;感觉自己被困在数字迷宫中吗&#xff1f;无法编辑的文本、无法调整大小的图像以及签署感觉像是一件苦差事的文档&#xff1f;好吧&#xff0c;不用再担心了&#xff01;本指南解开了在 Windows 上掌握 PDF 的秘密&#xff0c;其中包含 10 款适用于 …

图数据库Neo4J入门——Neo4J下载安装+Cypher基本操作+《西游记》人物关系图实例

这里写目录标题 一、效果图二、环境准备三、数据库设计3.1 人物节点设计3.2 关系设计 四、操作步骤4.1 下载、安装、启动Neo4J服务4.1.1 配置Neo4J环境变量4.1.2 启动Neo4J服务器4.1.3 启动Ne04J客户端 4.2 创建节点4.3 创建关系&#xff08;从已有节点创建关系&#xff09;4.4…

即插即用模块详解SCConv:用于特征冗余的空间和通道重构卷积

目录 一、摘要 二、创新点说明 2.1 Methodology 2.2SRU for Spatial Redundancy​编辑 2.3CRU for Channel Redundancy 三、实验 3.1基于CIFAR的图像分类 3.2基于ImageNet的图像分类 3.3对象检测 四、代码详解 五、总结 论文&#xff1a;https://openaccess.thecvf.c…

全网短剧搜索源码+短剧API接口 短剧下载 热门短剧 全开源可二开

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 pc端h5手机端全网短剧搜索前端源码分享 内含7000短剧资源(不支持在线播放&#xff09; 搜索API接口&#xff1a;文件内查看 全部短剧API接口&#xff1a;文件内查看 每日更新API接…