智能家居2 -- 实现网络控制模块

这一模块的思路和前面的语言控制模块很相似,差别只是调用TCP 去控制

废话少说,放码过来

增添/修改代码

socket_interface.c

#include <pthread.h>#include "socket_interface.h"
#include "control.h"
#include "socket.h"
#include "mq_queue.h"
#include "global.h"
#include <netinet/tcp.h> // 设置 tcp 心跳 的参数static int s_fd = -1;static int  tcpsocket_init(void)
{s_fd = socket_init(IPADDR,IPPORT);//return s_fd;return -1;
}static void tcpsocket_final(void) 
{close(s_fd);s_fd = -1;
}static void* tcpsocket_get(void *arg)
{int c_fd = -1;unsigned char buffer[BUF_SIZE];int ret = -1;struct sockaddr_in c_addr;mqd_t mqd = -1;ctrl_info_t * ctrl_info = NULL; int keepalive = 1;    // 开启TCP_KEEPALIVE选项int keepidle = 10;    // 设置探测时间间隔为10秒int keepinterval = 5; // 设置探测包发送间隔为5秒int keepcount = 3;    // 设置探测包发送次数为3次pthread_detach(pthread_self()); // 和主线程(他的父线程)分离printf("%s|%s|%d   s_fd = %d\n", __FILE__, __func__, __LINE__, s_fd);if(-1 == s_fd) // 判断是否初始化成功{s_fd = tcpsocket_init();if(-1 == s_fd){printf("tcpsocket_init error\n");pthread_exit(0);}}if(NULL != arg)ctrl_info = (ctrl_info_t*)arg;if(NULL != ctrl_info)mqd = ctrl_info->mqd;      if((mqd_t)-1 == mqd){pthread_exit(0);  }memset(&c_addr, 0, sizeof(struct sockaddr_in));int clen = sizeof(struct sockaddr_in);printf("%s thread start\n", __func__);while (1) // 一直等待接收{c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &clen); // 获得新的客户端 描述符if (c_fd == -1){continue;}ret = setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,sizeof(keepalive));if(-1 == ret){perror("setsockopt");break;}ret = setsockopt(c_fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(keepidle));if(-1 == ret){perror("setsockopt");break;}ret = setsockopt(c_fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval,sizeof(keepinterval));if(-1 == ret){perror("setsockopt");break;}ret = setsockopt(c_fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcount,sizeof(keepcount)); if(-1 == ret){perror("setsockopt");break;}// 打印调试信息printf("%s | %s | %d: Access a connection from %s:%d\n", __FILE__, __func__, __LINE__, inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));while (1){memset(buffer, 0, BUF_SIZE);ret = recv(c_fd, buffer, BUF_SIZE, 0); // 等待接收// 将接收到数据打印出来printf("%s|%s|%d,  0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);if (ret > 0){if(buffer[0] == 0xAA && buffer[1] == 0x55 &&buffer[4]==0x55 && buffer[5]==0xAA){printf("%s|%s|%d,  send: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);send_msg(mqd,buffer,ret); }}else if (0 == ret || -1 == ret) // 没读到,or 读到空{break;}}}pthread_exit(0);}struct  control tcpsocket_control ={.control_name = "tcpsocket",.init = tcpsocket_init,.final = tcpsocket_final,.get = tcpsocket_get,.set = NULL, //不需要实现 设置.next = NULL
};struct control *add_tcpsocket_to_ctrl_list(struct control *phead)
{//头插法实现 添加链表节点struct control *pnew = NULL;if(NULL == phead){phead = &tcpsocket_control; // 直接传入我们的 voice_control}else// 头结点非空 - 链表有数据{tcpsocket_control.next = phead; //把新的节点的next指向头结点phead = &tcpsocket_control; // 让心节点成为头结点}return phead;};



socket_interface.h

#ifndef ___SOCKET_INTERFACE_H___
#define ___SOCKET_INTERFACE_H___#include "control.h"
struct control *add_tcpsocket_to_ctrl_list(struct control *phead);#endif

修改的main.c

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>#include "control.h"
#include "mq_queue.h"
#include "voice_interface.h"
#include "socket_interface.h"
#include "global.h"// msg_queue_createint main() {pthread_t thread_id;struct control *control_phead = NULL;struct control *pointer = NULL;ctrl_info_t *ctrl_info = NULL;ctrl_info = (ctrl_info_t *)malloc(sizeof(ctrl_info_t));ctrl_info->ctrl_phead = NULL;ctrl_info->mqd = -1;int node_num = 0; // 统计节点数// 创建消息队列ctrl_info->mqd = msg_queue_create();if(-1 == ctrl_info->mqd)// 创建消息队列失败{printf("%s|%s|%d, mqd= %d\n",__FILE__,__func__,__LINE__,ctrl_info->mqd);return -1;}ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);ctrl_info->ctrl_phead = add_tcpsocket_to_ctrl_list(ctrl_info->ctrl_phead);//ctrl_info->ctrl_phead = add_fire_to_ctrl_list(ctrl_info->ctrl_phead);pointer = ctrl_info->ctrl_phead;while(NULL!=pointer) // 对所有控制结构体初始化,并且统计节点数{if(NULL != pointer->init){printf("%s|%s|%d   control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);pointer->init();}pointer = pointer->next;node_num++; // 统计节点数}// 根据节点的总数 --> 创建对应数目的线程pthread_t *tid = (pthread_t *)malloc(sizeof(int) *node_num);pointer = ctrl_info->ctrl_phead;for(int i=0;i<node_num;++i)//遍历所有节点{if(NULL != pointer->get){printf("%s|%s|%d   control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info); // 传入这个结构体参数,方便同时调用多组线程里面的API}pointer = pointer->next;}for(int i=0;i<node_num;++i){pthread_join(tid[i],NULL);}for(int i=0;i<node_num;++i){if(NULL != pointer->final)pointer->final(); // 接打开的使用接口关闭pointer = pointer->next;}msq_queue_final(ctrl_info->mqd);}

编译执行:

编译:

make

发送到arm-64平台

scp ./obj/smarthome  orangepi@192.168.1.11:/home/orangepi

执行:

sudo -E ./smarthome

/遇到如下报错 -- 解决:


scp: /home/orangepi/smarthome: Text file busy

kill -9 进程即可

 kill之后成功了

bind: Address already in use
 

要解决这个问题,您可以尝试以下步骤:

  1. 查找并关闭现有进程:使用 netstatlsof 或 ss 命令来查找正在监听该端口的进程,并关闭它。

     
    sudo netstat -tulnp | grep [端口号] 
    # 或者 
    sudo lsof -i :[端口号] 
    # 或者 
    sudo ss -tulnp | grep [端口号]
     

    找到进程ID(PID)后,使用 kill -9 命令来结束该进程。

  2. 重启计算机:如果无法确定哪个进程正在使用端口,或者无法结束该进程,您可以考虑重启计算机。

  3. 使用不同的端口:如果您只是想要快速测试您的应用程序,并且不关心特定的端口号,您可以尝试使用另一个端口。

TCP验证:

(注意发送格式 16进制)

否则你发送的数据很可能变成这样

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

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

相关文章

由北京车展想到的,技术红利时代的“重启”

北京车展刚刚落幕&#xff0c;雷军和周鸿祎成为网红&#xff0c;国产品牌站上王座。与此同时&#xff0c;马斯克“光速”访华&#xff0c;FSD酝酿入华再掀新竞争。华为在车展前发布的智驾新品牌“乾崑”&#xff0c;同样在现场广受关注。它们的精彩&#xff0c;让燃油车羡慕。 …

【Vue】pinia

pinia 官网:https://pinia.vuejs.org/zh/ 搭建 pinia 环境 第一步&#xff1a;npm install pinia --save 第二步&#xff1a;操作src/main.ts import { createApp } from vue import App from ./App.vue/* 引入createPinia&#xff0c;用于创建pinia */ import { createP…

新一代智慧音视频平台,企业必备新基建

随着5G、云计算、实时音视频、多模态、大模型、数字人等前沿技术的发展&#xff0c;企业与客户的交互方式正加速趋于移动化、视频化。 国家有关部门也相继出台系列政策法规&#xff0c;确保线上业务安全合规&#xff0c;以保障消费者权益。如&#xff0c;针对保险、银行、证券…

STM32快速入门(定时器之输入捕获)

STM32快速入门&#xff08;定时器之输入捕获&#xff09; 前言 本节主要讲解STM32利用通用定时器&#xff0c;在输入引脚出现指定电平跳变时&#xff0c;将CNT的值锁存到CCR寄存器当中&#xff0c;从而计算PWM波形的频率、占空比、脉冲间隔、电平持续时间等。其功能的应用有&…

浅谈自己用过最好用的AI工具概括

个人最经常用的AI工具的其实是Copilot&#xff0c;但是也有别的一些最好用的AI工具&#xff0c;包括&#xff1a; OpenAI GPT-3&#xff1a;这是一个自然语言生成模型&#xff0c;具有强大的语言理解和生成能力。它可以用于各种任务&#xff0c;如文字生成、自动回复和文本摘要…

brpc profiler

cpu profiler cpu profiler | bRPC MacOS的额外配置 在MacOS下&#xff0c;gperftools中的perl pprof脚本无法将函数地址转变成函数名&#xff0c;解决办法是&#xff1a; 安装standalone pprof&#xff0c;并把下载的pprof二进制文件路径写入环境变量GOOGLE_PPROF_BINARY_PA…

K8S快速入门

K8S快速入门 在学习k8s的过程&#xff0c;虽然官网给出的示例教程很简单&#xff0c;但是由于网络和环境的差异&#xff0c;导致实际操作的时候踩了很多坑&#xff0c;下面记录一下自己的操作步骤&#xff0c;方便需要的人参考&#xff0c;也方便以后的自己。 参考官网的资料…

Windows 10 中使用 Montreal-Forced-Aligner (MFA) 实现音频和文本强制对齐

文章目录 一、实现目标二、安装 Montreal-Forced-Aligner1、使用 Anaconda 虚拟环境2、修改默认下载路径3、安装 montreal-forced-aligner 及相关第三方包4、验证是否安装成功 三、下载声学模型和发音词典1、命令行方式下载2、手动方式下载 四、强制对齐1、准备音频及对应文本2…

短视频矩阵系统电脑端/手机版双端加盟saas技术源头开发

短视频矩阵系统是为了帮助用户更高效地管理、编辑、发布和分析短视频内容而设计的综合性平台。这种系统通常包含电脑端和手机端两个部分&#xff0c;每个部分都有其特定的功能模型&#xff0c;以适应不同设备的操作习惯和使用场景。以下是根据搜索结果中提供的信息&#xff0c;…

Debian是什么?有哪些常用命令

目录 一、Debian是什么&#xff1f; 二、Debian常用命令 三、Debian和CentOS的区别 四、Debian和CentOS的优缺点 五、Debian和CentOS的运用场景 一、Debian是什么&#xff1f; Debian是一种流行的开源Linux操作系统。 Debian是一个以Linux内核为基础的操…

vue3 element-plus表单form验证规则设置的require:true无效

必填项为空校验&#xff0c;valid第一次为true&#xff0c;再点值为false 引入FormInstance &#xff0c;校验代码改为以下&#xff1a; import { ElMessage, FormInstance } from element-plus const ruleFormRef ref<FormInstance>()const submitForm async (formEl:…

大模型市场爆发式增长,但生成式AI成功的关键是什么?

进入2024年&#xff0c;大模型市场正在爆发式增长。根据相关媒体的总结&#xff0c;2024年1-4 月被统计到的大模型相关中标金额已经达到2023年全部中标项目披露金额的77%左右&#xff1b;其中&#xff0c;从项目数量来看&#xff0c;应用类占63%、算力类占21%、大模型类占13%、…

(MATLAB)安装指南

参考链接&#xff1a;MATLAB2019a安装教程&#xff08;避坑版&#xff09;

软考中级-软件设计师(十)网络与信息安全基础知识

一、网络概述 1.1计算机网络的概念 计算机网络的发展&#xff1a;具有通信功能的单机系统->具有通信功能的多机系统->以共享资源为目的的计算机网络->以局域网及因特网为支撑环境的分布式计算机系统 计算机网络的功能&#xff1a;数据通信、资源共享、负载均衡、高…

社区智能奶柜:创业新机遇

社区智能奶柜&#xff1a;创业新机遇 在追求高质量生活的今天&#xff0c;健康食品成为大众焦点。社区智能奶柜适时登台&#xff0c;革新了居民获取新鲜牛奶的传统模式&#xff0c;为创业者开辟了一片蓝海市场。 一、新兴创业蓝海&#xff1a;牛奶随享站 日常膳食中&#xf…

uniapp 如何修改 IPA 文件信息页的本地化语言

实现效果&#xff1a; 最终会对应到苹果商店的语言&#xff1a; 例如微信的语言就有多个&#xff1a; 操作&#xff1a; 在 mainfest.json 源码视图中加入&#xff1a; 具体对应的语言key值可以参考Xcode中的语言代码 这个取决于打包后的 lproj 文件 将后缀ipa改成zip打开即…

MySQL —— 数据类型

一、数值类型 以上表格整理了用来表示数值类型的数据类型&#xff0c;其中&#xff0c;接下来将介绍和展示其中几个类型的使用和各种细节 1.tinyint 越界测试&#xff1a;建立一个包含tinyint类型的表格&#xff0c;插入各中数据去查看结果&#xff0c;并且尝试插入边界数据和…

【接地故障保护】剩余电流继电器及监控产品解决方案

安科瑞电气股份有限公司 祁洁 15000363176 一、产品型号 二、产品功能 1、对直接接触电击事故的防护 对直接接触电击事故的防护中&#xff0c;剩余电流继电器&#xff08;RCD&#xff09;只作为直接接触电击事故基本防护措施的补充保护措施&#xff08;不包括对相与相、相…

SQL注入实例(sqli-labs/less-1)

初始网页 从网页可知传递的参数名为 id&#xff0c;并且为数字类型 1、得知数据表有多少列 1.1 使用联合查询查找列数&#xff08;效率低&#xff09; http://localhost/sqli-labs-master/Less-1/?id1 union select 1,2 -- 1.2 使用order by查找列数&#xff08;效率高&…

OpenCV 入门(六) —— Android 下的人脸识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…