智能家居的蓝牙网关板块

一.项目介绍

1。智能家具以智能电视柜的网络中心、数据中心为核心,利用移动设备内嵌自主研发的APP,使用WIFI传输协议蓝牙传输协议进行命令集传送及数据交换,以终端IC内嵌WIFI、蓝牙控制协议实现对家具的无线控制功能。使用户可方便的通过手机进行数据交换、数据传送、影音播放、功能控制。

2.本项目主要为只能家具的蓝牙网关模块(接收手机端的消息,通过TCP/ud/mqtt协议发送给蓝牙网关。再转发到对应的端口)

3.以下是本次需要用到的函数

void get_local_time(char *buf, int bufsize);//获取当前时间

void *tcp_resc(void *arg);//tcp接收往蓝牙
void *udp_resc(void *arg);//udp接收往蓝牙
void *mqtt_resc(void *arg);//mqtt接收往蓝牙
int configure_serial(int fd);
void bule_send(unsigned char *ip,unsigned  char *buf);//接收蓝牙发的信息的线程函数
void my_msq_callback(struct mosquitto *msq,void * obj,const struct mosquitto_message *msg);
void *resc_pthread(void *arg);//接收蓝牙往其他端发线程
void tcp_send(char *ip_buf,char *port_buf,char *resc_buf);//将蓝牙的消息转发
void udp_send(char *ip_buf,char *port_buf,char *resc_buf);//将蓝牙的消息转发
void mqtt_send(char *ip_buf,char *port_buf,char *resc_buf);//将蓝牙的消息转发,并存到数据库
void my_sql(int arg1,char *arg2);

二.通讯功能实现

1.蓝牙的接收与发送

接收手机端蓝牙发送的消息

 int fd;                          // 文件描述符用于串行通信
    struct termios options;          // 用于存储和配置串行端口设置的结构
    unsigned char buffer[256];       // 用于读取串口数据的缓冲区
    int bytes_read;                  // 从串口读取的字节数

    fd = open("/dev/ttyUSB2", O_RDWR | O_NOCTTY | O_NDELAY);  // 尝试打开串行端口ttyUSB0

    if (fd == -1) {                  // 如果打开失败
        perror("Unable to open port"); // 打印错误信息
        return 1;                    // 退出程序
    } else {
        fcntl(fd, F_SETFL, 0);       // 设置文件描述符属性
        printf("Port is open.\n");  // 端口打开成功,打印消息
    }

    tcgetattr(fd, &options);         // 获取当前设备的配置

    cfsetispeed(&options, B115200);  // 设置输入波特率为115200
    cfsetospeed(&options, B115200);  // 设置输出波特率为115200

    options.c_cflag &= ~CSIZE;       // 清除数据位
    options.c_cflag |= CS8;          // 设置数据位为8
    options.c_cflag &= ~PARENB;      // 无奇偶校验
    options.c_cflag &= ~CSTOPB;      // 停止位为1
    options.c_iflag &= ~(IXON | IXOFF | IXANY);  // 不使用软件流控制
    options.c_cflag &= ~CRTSCTS;     // 不使用硬件流控制
    options.c_cflag |= (CLOCAL | CREAD);  // 忽略调制解调器的状态线,使能接收

    tcsetattr(fd, TCSANOW, &options);  // 将修改后的配置应用到设备

    printf("Port is configured.\n");  // 打印端口配置完成的消息

    while (1) {  // 无限循环
        tcflush(fd, TCIFLUSH);          // 清空输入缓冲区
        bytes_read = read(fd, buffer, sizeof(buffer) - 1);  // 从串行端口读取数据  
       if (bytes_read < 0) {  
            perror("Error reading from serial port");  // 如果读取时发生错误,则打印错误信息
            break;                     // 跳出无限循环
        }
        printf("%s",buffer);
       
    }
  
    close(fd);                        // 关闭串行端口

将电脑端消息通过蓝牙发送给手机

int configure_serial(int fd) {
    struct termios options;

    tcgetattr(fd, &options);  // 获取当前设备的配置

    cfsetispeed(&options, B115200);  // 设置输入波特率为115200
    cfsetospeed(&options, B115200);  // 设置输出波特率为115200

    options.c_cflag &= ~CSIZE;       // 清除数据位
    options.c_cflag |= CS8;          // 设置数据位为8
    options.c_cflag &= ~PARENB;      // 无奇偶校验
    options.c_cflag &= ~CSTOPB;      // 停止位为1
    options.c_iflag &= ~(IXON | IXOFF | IXANY);  // 不使用软件流控制
    options.c_cflag &= ~CRTSCTS;     // 不使用硬件流控制
    options.c_cflag |= (CLOCAL | CREAD);  // 忽略调制解调器的状态线,使能接收

    tcsetattr(fd, TCSANOW, &options);  // 将修改后的配置应用到设备
    return 0;
}
    int fd;
    unsigned char data_to_send[] = {0x11, 0x34, 0x0D};  // 要发送的数据

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);  // 尝试打开串行端口ttyUSB0

    if (fd == -1) {
        perror("Unable to open port");
        return 1;
    } else {
        fcntl(fd, F_SETFL, 0);
        printf("Port is open.\n");
    }

    configure_serial(fd);  // 配置串行端口

    printf("Port is configured.\n");
    printf("Sending data...\n");

    ssize_t bytes_written = write(fd, data_to_send, sizeof(data_to_send));  // 将数据写入串行端口

    if (bytes_written < 0) {
        perror("Error writing to serial port");
    } else {
        printf("Data sent successfully.\n");
    }

    close(fd);  // 关闭串行端口

2.mqtt的发送。

void mqtt_send(char *ip_buf,char *port_buf,char *resc_buf)
{

    int temp=atoi(resc_buf);
    char time_buf[22]="";
    int bufsize = sizeof(time_buf);  
    get_local_time(time_buf, bufsize);
    my_sql(temp,time_buf);

    mosquitto_lib_init();
    struct mosquitto *msq;
    msq=mosquitto_new("pub",true,port_buf);
    mosquitto_connect(msq,ip_buf,1883,2);
    mosquitto_publish(msq,NULL,port_buf,strlen(resc_buf),resc_buf,1,false);   

    // 断开MQTT连接并清理资源
    mosquitto_disconnect(msq);
    mosquitto_destroy(msq);
    mosquitto_lib_cleanup();
}

3.udp接收与发送

这里用将改功能写入线程函数,来保证电脑终端运行时一直在接收udp协议发送来的消息,当接收到消息后通过蓝牙转发到手机端

void *udp_resc(void *arg)
{

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("sockfd"); 
        return NULL;
    }
    struct sockaddr_in my_addr;
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(g_port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    int ret = bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));
    while (1)
    {
        struct sockaddr_in cli_addr; // 定义客户端地址结构体
        socklen_t cli_len = sizeof(cli_addr); // 定义地址结构体的长度

        unsigned short port = 0; // 定义用于存储端口的变量
        unsigned char ip[16] = ""; // 定义用于存储IP的数组

        unsigned char buf[128] = ""; 
        int len = 0; 
        len = recvfrom(sockfd, buf,sizeof(buf), 0, (struct sockaddr *)&cli_addr, &cli_len);

        if(len>0)
        {
            printf("*********udP*******\n"); 
            port = ntohs(cli_addr.sin_port); // 获取端口号
            inet_ntop(AF_INET, &cli_addr.sin_addr.s_addr,ip, 16); // 获取IP地址
            printf("%s:%hu %s\n", ip, port, buf); // 打印客户端的IP、端口和发送的数据
            bule_send(ip, buf);        

        }

    }

    return NULL; // 线程返回
}

当接收消息的线程接收到消息后,进行拆包,判断需要什么协议来转发这条消息,当判断为需要udp协议时,运行该函数

void udp_send(char *ip_buf,char *port_buf,char *resc_buf)
{
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    int flag=1;
    if(sockfd<0)
    {
        perror("socket:");
        return;
    }
    struct sockaddr_in my_addr;
    bzero(&my_addr,sizeof(my_addr));
    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(atoi(port_buf));
    inet_pton(AF_INET,ip_buf,&my_addr.sin_addr.s_addr);
    setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&flag,sizeof(flag));
    sendto(sockfd,resc_buf,strlen(resc_buf),0,(struct sockaddr *)&my_addr,sizeof(my_addr));
    close(sockfd);
}

TCP的接收和发送

和udp一样,tcp,mqtt,udp三个接收线程当接收到消息的时候调用蓝牙的送函数,转发其他端发来的消息

void *tcp_resc(void *arg)
{
    int sockfd= socket(AF_INET,SOCK_STREAM,0);
    if (sockfd<0)
    {
        perror("sockfd:");
        return NULL;
    }
    //printf("sockfd=%d\n",sockfd);

    //2.连接服务器connect
    //创建目的地址结构体
    struct sockaddr_in dst_addr;
    bzero(&dst_addr, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_port = htons(g_port);
    inet_pton(AF_INET, "ip", &dst_addr.sin_addr.s_addr);
    //使用连接函数连接
    connect(sockfd,(struct sockaddr *)&dst_addr,sizeof(dst_addr));

    //3.具体的功能
    while (1)
    { 
        struct sockaddr_in cli_addr; // 定义客户端地址结构体
        socklen_t cli_len = sizeof(cli_addr); // 定义地址结构体的长度

        unsigned char ip[16] = ""; // 定义用于存储IP的数组

        unsigned char buf[128] = ""; 
        int len = 0; 
        len=recv(sockfd, buf,sizeof(buf), 0);
        if (len>0)
        {   
            printf("*********TCP*******\n");      
            printf("%s %s\n", ip, buf); // 打印客户端的IP、端口和发送的数据
            bule_send(ip, buf);              

        }

    }
    close(sockfd);
    return NULL;
}
void tcp_send(char *ip_buf,char *port_buf,char *resc_buf)
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in dst_addr;
    bzero(&dst_addr,sizeof(dst_addr));
    dst_addr.sin_family=AF_INET;
    dst_addr.sin_port=htons(atoi(port_buf));
    inet_pton(AF_INET,ip_buf,&dst_addr.sin_addr.s_addr);
    connect(sockfd,(struct sockaddr*)&dst_addr,sizeof(dst_addr));
    send(sockfd,resc_buf,strlen(resc_buf),0);      
    return;
}

三.其他功能

1.数据库功能

连接数据库,将收到的信息存入到数据库

void history_sql(char *arg1,char *arg2,char *arg3,char *arg4)
{
    MYSQL mysql, *sock; // 定义mysql实例和指针

    //初始化数据库环境
    mysql_init(&mysql); // 用于初始化MYSQL对象,为后续的连接做准备。参数是要初始化的MYSQL对象的地址。

    //连接数据库
    sock = mysql_real_connect(&mysql, linux_ip, "名字", "1密码", "mqtt", 3306, NULL, 0);
    // 这个函数用于创建与MySQL服务器的连接。参数依次为:MYSQL对象的地址、服务器的IP地址、用户名、密码、数据库名、服务器的端口号、unix套接字(在这里没有使用,所以为NULL)、客户端标志(在这里没有使用,所以为0)

    if (sock == NULL) 
    {
        fprintf(stderr, "连接失败: %s\n", mysql_error(&mysql));
        return;
    }
    char sql_str[512];  // 或者根据实际情况分配足够的内存空间
    sprintf(sql_str, "insert into history(agr,ip,port,time) values('%s','%s','%s','%s')", arg1, arg2,arg3,arg4);
    int ret=mysql_real_query(&mysql,sql_str,strlen(sql_str));
    if(ret !=0)
    {
        perror("mysql_query:");
        return;
    }
    MYSQL_RES *res=mysql_store_result(&mysql);
    mysql_free_result(res);
    mysql_close(sock);
}

2.实时时间显示

获取当前系统的时间


void get_local_time(char *buf, int bufsize) {
    // 获取当前时间
    time_t rawtime;
    struct tm *timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);

    // 将时间格式化为字符串
    strftime(buf, bufsize, "%Y-%m-%d %H:%M:%S", timeinfo);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值