智能家居(3)---socket网络控制线程封装
封装socket网络线程实现对智能家居中各种灯光的控制
main.Pro(主函数)
#include <stdio.h>
#include "controlDevice.h"
#include "inputCommand.h"
#include <pthread.h>struct Devices *pdeviceHead = NULL; //设备工厂链表头
struct InputCommander *pcommandHead = NULL; //指令工厂链表头
struct InputCommander *socketHander = NULL;struct Devices* findDeviceByName(struct Devices *phead,char *name) //在设备链表中查找设备
{struct Devices *tmp = phead;if(tmp == NULL){printf("The devicesLink is NULL");return NULL;}else{while(tmp != NULL){if(strcmp(tmp->deviceName,name) == 0){return tmp;}tmp = tmp->next;}return NULL; }}struct InputCommander* findCommanderByName(struct InputCommander *phead,char *name) //控制链表查找相关控制
{struct InputCommander *tmp = phead;if(tmp == NULL){printf("The commanderLink is NULL");return NULL;}else{while(tmp != NULL){if(strcmp(tmp->commandName,name) == 0){return tmp;}tmp = tmp->next;}return NULL; }}void doCommand(struct InputCommander *cmd) //根据传入的命令控制相关设备
{struct Devices *tmp = NULL;if(strstr(cmd->command,"START")){ //初始化所有设备tmp = findDeviceByName(pdeviceHead,"bathroomLight");if(tmp != NULL) tmp->deviceInit(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"bedroomLight");if(tmp != NULL) tmp->deviceInit(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"livingroomLight");if(tmp != NULL) tmp->deviceInit(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"restaurantLight");if(tmp != NULL) tmp->deviceInit(tmp->pinNum);printf("The devices all init success\n");}else if(strstr(cmd->command,"OL1")){ //打开卫生间灯tmp = findDeviceByName(pdeviceHead,"bathroomLight");if(tmp != NULL) tmp->open(tmp->pinNum);printf("The bathroomLight already open\n");}else if(strstr(cmd->command,"CL1")){ //关闭卫生间灯tmp = findDeviceByName(pdeviceHead,"bathroomLight");if(tmp != NULL) tmp->close(tmp->pinNum);printf("The bathroomLight already close\n");}else if(strstr(cmd->command,"OL2")){ //打开卧室灯tmp = findDeviceByName(pdeviceHead,"bedroomLight");if(tmp != NULL) tmp->open(tmp->pinNum);printf("The bedroomLight already open\n");}else if(strstr(cmd->command,"CL2")){ //关闭卧室灯tmp = findDeviceByName(pdeviceHead,"bedroomLight");if(tmp != NULL) tmp->close(tmp->pinNum);printf("The bedroomLight already close\n");}else if(strstr(cmd->command,"OL3")){ //打开客厅灯tmp = findDeviceByName(pdeviceHead,"livingroomLight");if(tmp != NULL) tmp->open(tmp->pinNum);printf("The livingroomLight already open\n");}else if(strstr(cmd->command,"CL3")){ //关闭客厅灯tmp = findDeviceByName(pdeviceHead,"livingroomLight");if(tmp != NULL) tmp->close(tmp->pinNum);printf("The livingroomLight already close\n");}else if(strstr(cmd->command,"OL4")){ //打开餐厅灯tmp = findDeviceByName(pdeviceHead,"restaurantLight");if(tmp != NULL) tmp->open(tmp->pinNum);printf("The restaurantLight already open\n");}else if(strstr(cmd->command,"CL4")){ //关闭餐厅灯tmp = findDeviceByName(pdeviceHead,"restaurantLight");if(tmp != NULL) tmp->close(tmp->pinNum);printf("The restaurantLight already close\n");}else if(strstr(cmd->command,"ALL1")){ //打开所有的灯tmp = findDeviceByName(pdeviceHead,"bathroomLight");if(tmp != NULL) tmp->open(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"bedroomLight");if(tmp != NULL) tmp->open(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"livingroomLight");if(tmp != NULL) tmp->open(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"restaurantLight");if(tmp != NULL) tmp->open(tmp->pinNum);printf("The Light all open success\n");}else if(strstr(cmd->command,"ALL0")){ //关闭所有的灯tmp = findDeviceByName(pdeviceHead,"bathroomLight");if(tmp != NULL) tmp->close(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"bedroomLight");if(tmp != NULL) tmp->close(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"livingroomLight");if(tmp != NULL) tmp->close(tmp->pinNum);tmp = findDeviceByName(pdeviceHead,"restaurantLight");if(tmp != NULL) tmp->close(tmp->pinNum);printf("The Light all close success\n");}}void* read_pthread(void *data) //socket获取命令线程处理函数
{int n_read;while(1){memset(socketHander->command,0,sizeof(socketHander->command));n_read = read(socketHander->c_fd,socketHander->command,sizeof(socketHander->command));if(n_read < 0){perror("read");}else if(n_read > 0){printf("get %d message-->: %s",n_read,socketHander->command);doCommand(socketHander); //执行命令}else{printf("client quit\n");close(socketHander->c_fd);pthread_exit(NULL);}}
}void* socket_pthread(void *data) //socket控制线程处理函数
{int c_fd;pthread_t read_pth;struct sockaddr_in c_addr;memset(&c_addr,0,sizeof(struct sockaddr_in));socklen_t c_len = sizeof(c_addr);socketHander = findCommanderByName(pcommandHead,"socketServer");if(socketHander == NULL){printf("find socketServer error\n");pthread_exit(NULL);}if(socketHander->Init(socketHander) < 0){printf("socket init error\n");pthread_exit(NULL);}elseprintf("%s init success\n",socketHander->commandName);while(1){c_fd = accept(socketHander->s_fd,(struct sockaddr *)&c_addr,&c_len);if(c_fd == -1){perror("accept");}elseprintf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));socketHander->c_fd = c_fd;pthread_create(&read_pth,NULL,read_pthread,NULL);}}int main()
{pthread_t socket_pth;if(wiringPiSetup()<0){//初始化wiringPi外设库printf("wiringPi Init failed\n");return -1;}//1.指令工厂初始化pcommandHead = addSocketToCommandLink(pcommandHead); //将socket控制加入命令控制链表//2.设备控制工厂初始化pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead); //将卫生灯加入设备链表pdeviceHead = addbedroomLightToDeviceLink(pdeviceHead); //将卧室灯加入设备链表pdeviceHead = addRestaurantLightToDeviceLink(pdeviceHead); //将餐厅灯加入设备链表pdeviceHead = addLivingroomLightToDeviceLink(pdeviceHead); //将客厅灯加入设备链表pdeviceHead = addFireToDeviceLink(pdeviceHead); //将火灾检测加入设备链表pdeviceHead = addBeepToDeviceLink(pdeviceHead); //将蜂鸣器加入设备链表//3.线程池建立//3.2socket线程ret = pthread_create(&socket_pth,NULL,socket_pthread,NULL);if (ret != 0) {printf("Failed to create socketthread.\n");return -1;}//等待线程退出pthread_join(socket_pth,NULL);return 0;
}
inputCommand.h(控制类)
#include <wiringPi.h>
#include <stddef.h>
#include <wiringSerial.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>struct InputCommander
{char commandName[128]; //命令名字char command[32]; //具体命令char deviceName[128]; //打开的设备名,比如串口char port[12]; //端口号char ipAddress[32]; //ip地址int (*Init)(struct InputCommander *commder);int (*getCommand)(struct InputCommander *commder);int fd; //文件描述符int baud; //波特率int s_fd; //socket服务端文件描述符int c_fd; //客户端文件描述符char log[1024]; //日志struct InputCommander *next;
};struct InputCommander *addSocketToCommandLink(struct InputCommander *phead); //socket控制加入命令控制链表
socketControl.c(socket)
#include "inputCommand.h"int socketInit(struct InputCommander *socketMes)
{int s_fd;//服务端struct sockaddr_in s_addr;memset(&s_addr,0,sizeof(struct sockaddr_in));//1.sockets_fd = socket(AF_INET,SOCK_STREAM,0); //创建套接字if(s_fd == -1){perror("socket");exit(-1);}//2.binds_addr.sin_family = AF_INET;s_addr.sin_port = htons(atoi(socketMes->port)); //将主机字节序的端口号转换为网络字节序inet_aton(socketMes->ipAddress,&(s_addr.sin_addr)); //转换ip地址为网络字节序bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)); //绑定相关的网络信息,如ip地址和端口号//3.listenlisten(s_fd,10);//监听,可连接10个客户端 printf("socket Server listen success......\n");socketMes->s_fd = s_fd;return s_fd;}struct InputCommander socketControl = {.commandName = "socketServer",.command = {0},.port = "8090",.ipAddress = "192.168.31.227",.Init = socketInit,.getCommand = socketGetCommand,.log = {0},.next = NULL,};struct InputCommander *addSocketToCommandLink(struct InputCommander *phead)
{if(phead == NULL){return &socketControl;}else{socketControl.next=phead;phead = &socketControl;return phead;}
}
相关文章:
智能家居(3)---socket网络控制线程封装
封装socket网络线程实现对智能家居中各种灯光的控制 main.Pro(主函数) #include <stdio.h> #include "controlDevice.h" #include "inputCommand.h" #include <pthread.h>struct Devices *pdeviceHead NULL; //设备工厂链表…...
ubuntu 安装 emscripten 时 install latest 安装报错问题
学习官网参考:Compiling a New C/C Module to WebAssembly - WebAssembly | MDN (mozilla.org) 报错信息 形如: Error: Downloading URL https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/b90507fcf011da61bacfca613569…...
concrt140.dll丢失怎么恢复?教你5种修复方法
首先介绍一下concrt140.dll是什么 concrt140.dll是Microsoft Visual C Redistributable for Visual Studio 2015所需的一个动态链接库文件。它是用于支持C程序运行的重要组件之一。当系统中缺少或丢失concrt140.dll文件时,可能会导致一些程序无法正常运行。 首先&a…...
【Vue-Router】路由入门
路由(Routing)是指确定网站或应用程序中特定页面的方式。在Web开发中,路由用于根据URL的不同部分来确定应用程序中应该显示哪个内容。 构建前端项目 npm init vuelatest //或者 npm init vitelatest安装依赖和路由 npm install npm instal…...
蓝牙耳机运动耳机哪个好、好用的运动蓝牙耳机推荐
如今的蓝牙耳机已经成为手机的最佳伴侣,也是运动爱好者的必备装备。然而,在众多蓝牙耳机中做出选择可能会让人感到困惑。其实,在选购运动蓝牙耳机时需要注意的事项还挺多的,比如舒适度、稳定性和音质等多个方面,逐一对照这些要点来…...
大数据面试题:Kafka的ISR机制
面试题来源: 《大数据面试题 V4.0》 大数据面试题V3.0,523道题,679页,46w字 可回答:1)从ISR踢出去之后呢;2)一般Leader怎么判断Follower挂掉? 参考答案: …...
Windows:解决MySQL登录ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using passwor=YES)问题
我在下载的MySQL是8.0.32版本,刚下的时候没什么问题第二天启动MySQL服务就出现了 ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES) 或 ERROR 1045 (28000): Access denied for user rootlocalhost (using password: NO) 这样的问题…...
springboot整合kafka多数据源
整合kafka多数据源 项目背景依赖配置生产者消费者消息体 项目背景 在很多与第三方公司对接的时候,或者处在不同的网络环境下,比如在互联网和政务外网的分布部署服务的时候,我们需要对接多台kafka来达到我们的业务需求,那么当kafk…...
基于CentOS 7 配置nginx负载均衡
搭建负载均衡服务的需求如下: 1 ) 把单台计算机无法承受的大规模并发访问或数据流量分担到多台节点设备上,分别进行处理, 减少用户等待响应的时间, 提升用户体验。 2 ) 单个重负载的运算分担到多台节点设备上做并行处理ÿ…...
WordToPDF2.java
用Java将Word转PDF 本例子测试了spire.doc.free-3.9.0.jar的包 <dependency><groupId> e-iceblue </groupId><artifactId>spire.doc.free</artifactId><version>3.9.0</version></dependency> package word;import com.spire.…...
k8s服务注册发现
Service 是 将运行在一个或一组pod上的网络应用程序公开为网络服务的方法。 定义service前端为service名称、ip、端口等不变的部分,后端为符合标签选择的pod集合 注册 通过api server提交注册service请求到DNSservice随后得到clusterIP(虚拟ip地址&am…...
IK分词器升级,MySQL热更新助一臂之力
ik分词器采用MySQL热更新 官方所给的IK分词器只支持远程文本文件热更新,不支持采用MySQL热更新,没关系,这难不倒伟大的博主,给哈哈哈。今天就来和大家讲一下如何采用MySQL做热更新IK分词器的词库。 一、建立数据库表 CREATE…...
泛微 E-Office文件上传漏洞复现
声明 本文仅用于技术交流,请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 文章作者拥有对此文章的修改和解释权。如欲转载或传播此文章,…...
bug的生命周期
bug的生命周期 bugbug的生命周期bug等级 bug 当且仅当规格说明书是存在的并且正确的,程序和规格说明书之间的不匹配才是错误当产品规格说明书没有提到时,以用户需求为准,当程序最终没有实现用户的合理预期的功能要求时,就是软件错…...
mysql分库分表相关
3小时快速上手sharding-jdbc 百亿级数据 分库分表 后面怎么分页查询? Java实战:教你如何进行数据库分库分表...
云原生k8s---资源限制、探针
目录 一:资源限制 1、资源限制原因 2、Pod 和 容器 的资源请求和限制 3、CPU 资源单位 4、内存 资源单位 5、事例 (1)事例一 (2)事例二 二:重启策略 1、重启策略模式 2、事例 三:探针…...
html2canvas生成图片地址Base64格式转成blob在转成file(二进制)可正常发送(保姆教程,复制粘贴可用)
开始: 最终结果: 1. html2canvas方法生成的图片地址已Base64编码形式放在img标签src中可直接展示生成的图片(注意页面标签获取位置,还有个setTimeout页面渲染需要时间) setTimeout(function () {var result {};v…...
将Linux上的cpolar内网穿透配置为开机自启动——“cpolar内网穿透”
将Linux上的cpolar内网穿透配置为开机自启动 文章目录 将Linux上的cpolar内网穿透配置为开机自启动前言一、进入命令行模式二、输入token码三、输入内网穿透命令 前言 我们将cpolar安装到了Ubuntu系统上,并通过web-UI界面对cpolar的功能有了初步了解。当然cpolar除…...
微信小程序data-item设置获取不到数据的问题
微信小程序data-item设置获取不到数据的问题 简单说明: 在微信小程序中,通过列表渲染使用wx:for根据数组中的每一项重复渲染组件。同时使用bindtap给每一项绑定点击事件clickItem,再通过data-item绑定数据。 **问题:**通过data-i…...
创建百度百科需要什么条件?
随着互联网的发展,人们越来越依赖于搜索引擎获取信息。百度作为中国最大的搜索引擎之一,旗下的百科词条已成为人们获取知识的重要来源。创建百度百科需要什么条件呢?接下来伯乐网络传媒就来给大家讲一讲。 首先,你需要有一个百度…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
ffmpeg(三):处理原始数据命令
FFmpeg 可以直接处理原始音频和视频数据(Raw PCM、YUV 等),常见场景包括: 将原始 YUV 图像编码为 H.264 视频将 PCM 音频编码为 AAC 或 MP3对原始音视频数据进行封装(如封装为 MP4、TS) 处理原始 YUV 视频…...
IP选择注意事项
IP选择注意事项 MTP、FTP、EFUSE、EMEMORY选择时,需要考虑以下参数,然后确定后选择IP。 容量工作电压范围温度范围擦除、烧写速度/耗时读取所有bit的时间待机功耗擦写、烧写功耗面积所需要的mask layer...
