当前位置: 首页 > news >正文

项目名称:智能家居边缘网关项目

一,项目介绍

软件环境: C语言
硬件环境: STM32G030C8TX单片机开发板
开发工具: Linux平台GCC交叉编译环境以及ukeil

(1)边缘网关概念

  边缘网关是部署在网络边缘侧的网关,通过网络联接、协议转换等功能联接物理和数字世界,提供轻量化的联接管理、实时数据分析及应用管理功能。比较常见的就是智能家居中智能音箱(蓝牙网关)+路由器(wifi网关),工厂里的工业网关等。它们通常扮演着一个区域内中心网关的功能,即负责终端设备的网络连接,也负责各终端数据的采集以及远程控制。同时,又提供数据上云的功能。

  

(2)包含知识点

两大网联网场景:消费物联网、工业物联网两大场景全覆盖

边缘网关新概念:物联网边缘网关中边缘采集、边缘计算两大主流技术

基础综合运用:C、shell、Makefile、C++、QT、单片机、数据库等基础知识大融合

Linux开发技术点:进程间通信、多线程程序设计、文件操作、网络编程、应用协议

物联网主流通信技术:Json、Modbus、mqtt

各种调试工具学习:mqtt.fx、modbus slave、modbus poll、wireshark、网络调试、串口调试等

二,产品需求矩阵

上位机:搜索界面,设备信息显示和控制界面,监控界面 ,历史数据查询,边缘计算

网关:上报模块,公有云模块,搜索响应模块,数据存储模块,内置网页,各采集模块,视频流模块

设备端:stm32模块,modbus模块

三,全局点表

点表使用

真实物联网场景中,点表通过客户端界面(上位机或者web页面)编辑,生成json文件后下发给设备,设备解析使用。

四,modbus采集进程

 modbus采集模块实现了modbus工业设备的通信对接,向上通过modbusTCP协议采集单片机的数据,并刷新到共享内存,以便上报模块进程使用。向下接收来自上报模块的JSON控制指令,解析后,转换为标准的modbusTCP指令后通过网络发送给设备,实现设备的控制。

(1)主程序:

int main(int argc, char const *argv[])
{INIT_LIST_HEAD(&head);FILE *fd = fopen("./node.json", "r");if (fd == NULL){perror("fopen err\n");}//定位文件末尾操作fseek(fd, 0, SEEK_END);//计算文件的大小int len = ftell(fd);//定位文件开头操作fseek(fd, 0, SEEK_SET);char *p = (char *)malloc(len + 1);fread(p, 1, len, fd);cJSON *root = NULL;//把传入的字符串转成cJSON的结构(反序列化)root = cJSON_Parse(p);if (root == NULL){perror("err parse\n");//return -1;}//版本cJSON *item = cJSON_GetObjectItem(root, "version");printf("version =%s\n", item->valuestring);item = cJSON_GetObjectItem(root, "mb_dev");char *IP = cJSON_GetObjectItem(item, "addr")->valuestring;int pot = cJSON_GetObjectItem(item, "port")->valueint;printf("ip=%s port=%d\n", IP, pot); //解析端口和设备地址//解析modbuscJSON *ROO = cJSON_GetObjectItem(root, "modbus");cJSON *tem = cJSON_GetObjectItem(ROO, "data");int array_size = cJSON_GetArraySize(tem); //数组的大小cJSON *JS_tem = tem->child;               //子对象for (int i = 0; i < array_size; i++){struct mb_node_list *arr = (struct mb_node_list *)malloc(sizeof(struct mb_node_list));printf("key=%d\n", cJSON_GetObjectItem(JS_tem, "key")->valueint);printf("name=%s\n", cJSON_GetObjectItem(JS_tem, "name")->valuestring);printf("addr=%d\n", cJSON_GetObjectItem(JS_tem, "addr")->valueint);printf("type=%d\n", cJSON_GetObjectItem(JS_tem, "type")->valueint);arr->node.key = cJSON_GetObjectItem(JS_tem, "key")->valueint;arr->node.addr = cJSON_GetObjectItem(JS_tem, "addr")->valueint;list_add(&arr->list, &head);JS_tem = JS_tem->next;}//1,创建实例//modbus_t *ctx = modbus_new_tcp(argv[1], atoi(argv[2]));modbus_t *ctx = modbus_new_tcp(IP, pot);//2,设置从机IDmodbus_set_slave(ctx, 1);//3,和主机进行连接int slave = modbus_connect(ctx);if (slave != 0){perror("connect err");return -1;}else{printf("连接成功!!!!\n");}//数据采集线程if (pthread_create(&tid, NULL, mythread, ctx) != 0){perror("pthread_create err");return -1;}//指令控制if (pthread_create(&tid, NULL, controlthread, ctx) != 0){perror("pthread_create_control err");return -1;}pthread_detach(tid);while (1);//6,释放Modbus实例modbus_free(ctx);//7,关闭套接字modbus_close(ctx);return 0;
}

(2)数据采集线程:

//数据采集线程
void *mythread(void *arg)
{uint16_t data[1024] = {};uint16_t data1[1024] = {};uint8_t dest[1024] = {};int ret = -1;ret = shm_init(&para, "shm_test", MAX_NODE_SIZE); //初始化if (ret < 0){perror("shm_init err\n");//return -1;}//获取共享内存的地址并将其赋值给指针变量addrvoid *addr = shm_getaddr(&para);if (addr == NULL){perror("shm_getaddr err\n");//return -1;}int *p = NULL;p = addr;printf("Address=%p\n", p);int *num = addr;struct std_node *add = (addr + sizeof(int));modbus_t *ctx = (modbus_t *)arg;while (1){sleep(2);list_for_each(pos, &head){tmp1 = list_entry(pos, struct mb_node_list, list);//温度if (tmp1->node.key == 101){modbus_read_input_registers(ctx, tmp1->node.addr - 1, 2, data);}//湿度else if (tmp1->node.key == 102){modbus_read_input_registers(ctx, tmp1->node.addr - 1, 2, data + 2);}//空调开关else if (tmp1->node.key == 103){modbus_read_bits(ctx, tmp1->node.addr - 1, 2, dest);//printf("空调开关= %u  ", dest[0]);}//空调的温度,//读取保持寄存器(功能码 0x3)else if (tmp1->node.key == 104){modbus_read_registers(ctx, tmp1->node.addr , 2, data1);}//风扇开关else if (tmp1->node.key == 105){modbus_read_bits(ctx, tmp1->node.addr - 1, 2, dest + 2);}//风扇档位1档,2档,3档else if (tmp1->node.key == 106){modbus_read_registers(ctx, tmp1->node.addr , 2, data1 + 2);}printf("温度寄存器= %u  湿度寄存器= %u\n", data[0], data[2]);printf("空调温度的监测= %u  风扇的档位=%u\n", data1[0], data1[2]);printf("空调开关的状态:=%u 风扇开关的状态:=%u\n", dest[0], dest[1]);}
/* 读取的方式modbus_read_input_registers(ctx, 0, 4, data);//读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04)//温度,湿度printf("温度寄存器= %u  湿度寄存器= %u\n", data[0], data[2]);//空调的温度,风扇档位1档,2档,3档//读取保持寄存器(功能码 0x3)modbus_read_registers(ctx, 0, 4, data1);printf("空调温度的监测= %u  风扇的档位=%u\n", data1[0], data1[2]);//空调开关和风扇开关//读取线圈或者离散量输出状态(功能码 0x1)modbus_read_bits(ctx, 0, 4, dest);printf("空调开关的状态:=%u 风扇开关的状态:=%u\n", dest[0], dest[1]);
*/for (int i = 0; i < *num; i++){if (add[i].key == 101) //温度{add[i].new_val.f_val = modbus_get_float_dcba(data);printf("Temperature sensor=%f\n", add[i].new_val.f_val);if (add[i].new_val.f_val != 0){add[i].ret = 0;}else{add[i].ret = -1;printf("Temperature sensor err:=%d\n", add[i].ret);}}else if (add[i].key == 102) //湿度{add[i].new_val.f_val = modbus_get_float_dcba(data + 2);printf("Humidity sensor=%f\n", add[i].new_val.f_val);if (add[i].new_val.f_val != 0){add[i].ret = 0;}else{add[i].ret = -1;printf("Humidity sensor err:=%d\n", add[i].ret);}}else if (add[i].key == 103) //空调开关{add[i].new_val.b_val = dest[0];printf("air conditioning switch=%d\n", add[i].new_val.b_val);if (add[i].new_val.b_val != 0){add[i].ret = 0;}else{add[i].ret = -1;printf("air conditioning switch err:=%d\n", add[i].ret);}}else if (add[i].key == 104) //空调的温度{add[i].new_val.f_val = modbus_get_float_dcba(data1);printf("air conditioning temperature=%f\n", add[i].new_val.f_val);if (add[i].new_val.f_val != 0){add[i].ret = 0;}else{add[i].ret = -1;printf("air conditioning temperature err:=%d\n", add[i].ret);}}else if (add[i].key == 105) //风扇开关{add[i].new_val.b_val = dest[1];printf("Fan switch=%d\n", add[i].new_val.b_val);if (add[i].new_val.b_val != 0){add[i].ret = 0;}else{add[i].ret = -1;printf("Fan switch err:=%d\n", add[i].ret);}}else if (add[i].key == 106) ///风扇档位控制,1档,2档,3档{add[i].new_val.f_val = modbus_get_float_dcba(data1 + 2);printf("Fan switch control=%f\n", add[i].new_val.f_val);if (add[i].new_val.f_val != 0){add[i].ret = 0;}else{add[i].ret = -1;printf("Fan switch err:=%d\n", add[i].ret);}}}for (int i = 0; i < 6; i++){if (add[i].key == 101){printf("key=%d new_val=%f\n", add[i].key, add[i].new_val.f_val);}else if (add[i].key == 102){printf("key=%d new_val=%f\n", add[i].key, add[i].new_val.f_val);}else if (add[i].key == 103){printf("key=%d new_val=%d\n", add[i].key, add[i].new_val.b_val);}else if (add[i].key == 104){printf("key=%d new_val=%f\n", add[i].key, add[i].new_val.f_val);}else if (add[i].key == 105){printf("key=%d new_val=%d\n", add[i].key, add[i].new_val.b_val);}else if (add[i].key == 106){printf("key=%d new_val=%f\n", add[i].key, add[i].new_val.f_val);}}sleep(1);}//free(tmp1);// tmp1 = NULL;shm_del(&para);pthread_exit(NULL);
}

(3)指令控制进程:

//指令控制
void *controlthread(void *arg)
{modbus_t *ctx = (modbus_t *)arg;struct msg msg;//反序列化msg.mtype = 1;while (1){// u_int16_t buf[4] = {444};// u_int16_t buf1[4] = {1662};//modbus_write_registers(ctx,40000,2,buf);//modbus_write_registers(ctx,40002,2,buf1);//modbus_write_registers(ctx,40003,2,buf);//modbus_write_registers(ctx,40005,4,buf );//modbus_write_register(ctx,0, 12);//modbus_write_register(ctx,2, 12);if (msg_queue_recv("modbus", &msg, sizeof(msg), 1, 0) > 0){cJSON *root = cJSON_Parse(msg.mdata);if (NULL == root){printf("err parse\n");//return -1;}//cJSON *item;//item = cJSON_GetObjectItem(root, "data"); //解析对象//解析key的值cJSON *login_key = cJSON_GetObjectItem(root, "key");int identifying_Key = login_key->valueint;printf("key=%d\n", identifying_Key); //打印此时的key值//解析val的值login_key = cJSON_GetObjectItem(root, "val");int identifying_val = atoi(cJSON_GetObjectItem(root, "val")->valuestring);printf("val=%d\n", identifying_val);//遍历链表list_for_each(pos, &head){tmp = list_entry(pos, struct mb_node_list, list);if (identifying_Key == tmp->node.key){if (identifying_Key == 103) //空调开关{modbus_write_bit(ctx, tmp->node.addr - 1, identifying_val);}else if (identifying_Key == 104) //空调温度控制{uint16_t buf[4];modbus_set_float_dcba((float)atof(cJSON_GetObjectItem(root, "val")->valuestring), buf);modbus_write_registers(ctx, tmp->node.addr, 2, buf);}else if (identifying_Key == 105) //风扇开关{modbus_write_bit(ctx, tmp->node.addr - 1, identifying_val);}else if (identifying_Key == 106) //风扇档位控制,1档,2档,3档{uint16_t buf[4];modbus_set_float_dcba((float)atof(cJSON_GetObjectItem(root, "val")->valuestring), buf);modbus_write_registers(ctx, tmp->node.addr, 2, buf);}}}}}pthread_exit(NULL);pause();
}

五,STM32

●STM32采集模块
stm32采集模块实现了stm32设备的通信对接,向上通过串口协议采集单片机的数据,
并刷新到共享内存,以便上报模块进程使用。
向下接收来自上报模块的JSON控制指令,解析后,
转换为相应的控制指令后通过串口发送给设备,实现设备的控制。

●单片机设备模块
单片机模拟了智能家居系统的设备场景,分别实现了传感器数据采集上报、设备的远程控制等功能。
通过ADC采集光敏传感器,并按照上报协议通过串口发送给网关设备。
接收来自网关的控制指令,通过JSON反序列化后,进行相应的设备控制。
呼吸灯来表示设备运行状态,按键模拟墙壁开关同步模拟灯光控制。

(1)需求分析

  • 采集类传感器使用光敏度传感器。
  • 蓝LED模拟智能灯,可以采集到灯状态并可远程控制;五向按键作为灯控开关(家居本地控制)。
  • 绿色灯作为呼吸灯,1S闪烁一次,表示设备运行正常。
  • 蓝灯表示网络连接状态,如果连接wifi并成功连接服务器后,蓝灯常亮(wifi连接模式)。
  • 每隔2s采集一次传感器数据智能灯的状态电池电量信息,组包主动上报给网关。
  • 接收来自网关的控制指令,并对智能灯做相应的控制。

(2)技术点分析

  • GPIO
  • 串口通信
  • 串口中断
  • GPIO中断
  • 硬件定时器
  • ADC采集
  • 网络调试(wifi连接模式)

注意:这种方式很直观,发送前需要对发送的数据进行JSON的序列化动作。

  • 单片机的栈空间比较小,如果使用cJSON序列化时候,在串口调试助手发现输出不正常时,一般是栈空间不够了,此时可以考虑增大栈空间,可以直接从cubeMX直接进行调整。

 (3)Linux中采集和控制代码

主线程:    // 读取串口数据(数据采集)

int main(int argc, char const *argv[])
{fd = open("/dev/ttyUSB0", O_RDWR);if (fd < 0){perror("open err");return -1;}elseprintf("open device success\n");serial_init(fd); //设置串口属性//创建线程pthread_t tid;if (pthread_create(&tid, NULL, my_pthread, NULL) != 0){perror("pthread create err");return -1;}printf("this is father\n");char buf[1024] = {0}; //存放读串口数据static struct shm_param para;int ret = -1;// 创建共享内存ret = shm_init(&para, "shm_test", 1024);if (ret < 0){return -1;}// 获取共享内存地址struct std_node *addr = shm_getaddr(&para);if (addr == NULL){return -1;}while (1){// 读取串口数据if (read(fd, buf, sizeof(buf)) < 0){perror("read err");return -1;}printf("cj_buf=%s\n", buf);// 反序列化cJSON *root = cJSON_Parse(buf);if (NULL == root){printf("parse err\n");return -1;}printf("*****反序列化*****\n");cJSON *data = NULL;cJSON *tmp = NULL;cJSON *item = NULL;data = cJSON_GetObjectItem(root, "data");int n = cJSON_GetArraySize(data);struct std_node buffer[n - 1];for (int i = 0; i < n; i++){tmp = cJSON_GetArrayItem(data, i);item = cJSON_GetObjectItem(tmp, "key");buffer[i].key = item->valueint;printf("%s=%d\n", item->string, item->valueint);item = cJSON_GetObjectItem(tmp, "val");if (buffer[i].key == 301) //传感器{buffer[i].type = 3;buffer[i].dev_type = buffer[i].key / 100;buffer[i].old_val.f_val = item->valueint;buffer[i].new_val.f_val = item->valueint;}else if (buffer[i].key == 302) //电池{buffer[i].type = 2;buffer[i].dev_type = buffer[i].key / 100;buffer[i].old_val.i_val = item->valueint;buffer[i].new_val.i_val = item->valueint;}else if (buffer[i].key == 303) //灯状态{buffer[i].type = 2;buffer[i].dev_type = buffer[i].key / 100;buffer[i].old_val.i_val = item->valueint;buffer[i].new_val.i_val = item->valueint;}//打印查看采集的值printf("%s=%d\n", item->string, item->valueint);buffer[i].ret = 0;}cJSON_Delete(root);}pthread_join(tid, NULL);return 0;
}

线程://从消息队列中读cjson(控制指令通过串口发给单片机)

void *my_pthread(void *arg)
{printf("this is son\n");struct msgbuf r_buf;cJSON *r = cJSON_CreateObject();cJSON *d = cJSON_CreateArray();cJSON_AddItemToObject(r, "data", d);cJSON *i = cJSON_CreateObject();cJSON_AddItemToArray(d, i);cJSON_AddNumberToObject(i, "key", 303);cJSON_AddStringToObject(i, "name", "light");cJSON_AddStringToObject(i, "val", "1");char *q = cJSON_PrintUnformatted(r);r_buf.mtype = 1;strcpy(r_buf.mdata, q);msg_queue_send("stm32", &r_buf, sizeof(r_buf), 0);printf("r_buf=%s\n", r_buf.mdata);free(q);cJSON_Delete(r);while (1){//从消息队列中读cjsonstruct msgbuf recv_buf;int t = msg_queue_recv("stm32", &recv_buf, sizeof(recv_buf), 0, 0);if (t < 0){perror("msg recv err");return NULL;}printf("%s\n", recv_buf.mdata);// 反序列化cJSON *msg_root = cJSON_Parse(recv_buf.mdata);if (NULL == msg_root){printf("parse err\n");return NULL;}int msg_key, msg_val;cJSON *msg_item = NULL;cJSON *msg_data = cJSON_GetObjectItem(msg_root, "data");int cout = cJSON_GetArraySize(msg_data);printf("*************\n");for (int i = 0; i < cout; i++){cJSON *tmp = cJSON_GetArrayItem(msg_data, i);msg_item = cJSON_GetObjectItem(tmp, "key");msg_key = msg_item->valueint;printf("%s=%d\n", msg_item->string, msg_item->valueint);msg_item = cJSON_GetObjectItem(tmp, "name");printf("%s=%s\n", msg_item->string, msg_item->valuestring);msg_item = cJSON_GetObjectItem(tmp, "val");msg_val = atoi(msg_item->valuestring);printf("%s=%s\n", msg_item->string, msg_item->valuestring);}cJSON_Delete(msg_root);// 序列化if (msg_key == 303){cJSON *root = cJSON_CreateObject();cJSON *data = cJSON_CreateArray();cJSON_AddItemToObject(root, "data", data);cJSON *item3 = cJSON_CreateObject();cJSON_AddItemToArray(data, item3);cJSON_AddNumberToObject(item3, "key", 303);cJSON_AddStringToObject(item3, "name", "light");cJSON_AddNumberToObject(item3, "val", msg_val);char *p = cJSON_PrintUnformatted(root);printf("ctronl_cjson=%s\n", p);//写串口if (write(fd, p, strlen(p)) < 0){perror("write err");return NULL;}free(p);cJSON_Delete(root);}}pthread_exit(NULL);
}

(4)ukeil工程

main.c() LED灯五项按键中断, 串口接受控制指令,ADC采集

五项按键

//按键中断
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin==GPIO_PIN_8){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8));//抬手检测}
}

串口接受控制指令

//每次达到上述条件后,会触发此中断,每次触发中断缓冲区数据就是完整一包数据
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if(huart->Instance == USART1){
//		printf("RxBuf is %s\n", RxBuf);//这里来解析命令,并做出相应的反应
//		char dev_name[32]={0};cJSON* recv_root=cJSON_Parse(RxBuf);
//		if(NULL==recv_root)
//		{
//			printf("parse err\n");
//		}cJSON*recv_data=cJSON_GetObjectItem(recv_root,"data");int count=cJSON_GetArraySize(recv_data);for(int i=0;i<count;i++){cJSON*tmp=cJSON_GetArrayItem(recv_data,i);
//			printf("********zhongduan*******\n");cJSON* recv_item=NULL;recv_item=cJSON_GetObjectItem(tmp,"key");
//			printf("%s=%d\n", recv_item->string, recv_item->valueint);int key=recv_item->valueint;//			recv_item=cJSON_GetObjectItem(tmp,"name");
//			printf("%s=%s\n", recv_item->string, recv_item->valuestring);
//			strcpy(dev_name,recv_item->valuestring);recv_item=cJSON_GetObjectItem(tmp,"val");
//			printf("%s=%d\n", recv_item->string, recv_item->valueint);int val=recv_item->valueint;
//			int val=atoi(recv_item->valueint);//控制灯if(key==303){//开灯if(val==1){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);}//关灯else if(val==0){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);}}cJSON_Delete(recv_root);}memset(RxBuf,0,1024);//再次设置此中断HAL_UARTEx_ReceiveToIdle_IT(&huart1,RxBuf,1024);}
}

ADC采集 ,LED灯,呼吸灯

  /* USER CODE BEGIN WHILE */while (1){//呼吸灯for(int i=995;i>=0;i--){TIM3->CCR3=i;HAL_Delay(1);}for(int i=0;i<995;i++){TIM3->CCR3=i;HAL_Delay(1);}//		启动adc开始转换HAL_ADC_Start(&hadc1);//		获取转换结果while(!(ADC1->ISR&(1<<2)));bat=HAL_ADC_GetValue(&hadc1);while(!(ADC1->ISR&(1<<3)));light=HAL_ADC_GetValue(&hadc1);//		停止转换HAL_ADC_Stop(&hadc1);//		printf("bat=%d light=%d\n",bat,light);
//		HAL_Delay(10);if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_SET){
//			printf("led_off\n");led_val=0;}else{
//			printf("led_on\n");led_val=1;}//序列化封装为json格式cJSON* root=cJSON_CreateObject();cJSON* data=cJSON_CreateArray();cJSON_AddItemToObject(root,"data",data);cJSON* item=cJSON_CreateObject();cJSON_AddItemToArray(data,item);cJSON_AddNumberToObject(item,"key",301);cJSON_AddStringToObject(item,"name","sensor");cJSON_AddNumberToObject(item,"val",light);cJSON* item2=cJSON_CreateObject();cJSON_AddItemToArray(data,item2);cJSON_AddNumberToObject(item2,"key",302);cJSON_AddStringToObject(item2,"name","bat");cJSON_AddNumberToObject(item2,"val",bat);cJSON* item3=cJSON_CreateObject();cJSON_AddItemToArray(data,item3);cJSON_AddNumberToObject(item3,"key",303);cJSON_AddStringToObject(item3,"name","light");cJSON_AddNumberToObject(item3,"val",led_val);char *p = cJSON_PrintUnformatted(root);HAL_UART_Transmit(&huart1,p,strlen(p),1000);
//		printf("cjson=%s\n",p);free(p);cJSON_Delete(root);//lcd屏显示sprintf(lcd_sensor,"%d\n",light);sprintf(lcd_bat,"%d\n",bat);sprintf(lcd_led,"%d\n",led_val);Gui_DrawFont_GBK16(25,30,WHITE,RED,"sensor:");Gui_DrawFont_GBK16(80,30,WHITE,RED,lcd_sensor);Gui_DrawFont_GBK16(35,45,WHITE,RED,"bat:");Gui_DrawFont_GBK16(78,45,WHITE,RED,lcd_bat);Gui_DrawFont_GBK16(35,60,WHITE,RED,"LED:");Gui_DrawFont_GBK16(78,60,WHITE,RED,lcd_led);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

 相关知识:

1,JSON数据交换格式

2,内核链表

3,共享内存,消息队列

通信组件(!!!!!!!!!!)

以下组件依赖临时目录,必须提前创建(tmp目录是内存型目录,如果重启了系统会消失,所以每次重启后注意重新创建下)

mkdir /tmp/ipc/shmem -p
mkdir /tmp/ipc/msgqueue/peer -p

4,GIT

 总结:

  • 强化编程基础
  • 迅速拓展知识面,训练自己的学习能力
  • 了解企业开发流程,提前感受团队项目开发过程

相关文章:

项目名称:智能家居边缘网关项目

一&#xff0c;项目介绍 软件环境: C语言 硬件环境: STM32G030C8TX单片机开发板 开发工具: Linux平台GCC交叉编译环境以及ukeil (1)边缘网关概念 边缘网关是部署在网络边缘侧的网关&#xff0c;通过网络联接、协议转换等功能联接物理和数字世界&#xff0c;提供轻量化的联接管…...

SciencePub学术 | 物联网类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 物联网类重点SCIE&EI征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 物联网类重点SCIE&EI 【期刊简介】IF&#xff1a;7.5-8.0&#xff0c;JCR1区&#xff0c;中科院1/2区TOP&#xff1b; 【出版社…...

EtherNet/IP转Modbus网关以连接AB PLC

本案例为西门子S7-1200 PLC通过捷米特Modbus转EtherNet/IP网关捷米特JM-EIP-RTU连接AB PLC的配置案例。 网关分别从ETHERNET/IP一侧和MODBUS一侧读写数据&#xff0c;存入各自的缓冲区&#xff0c;网关内部将缓冲区的数据进行交换&#xff0c;从而实现两边数据的传输。 网关做为…...

mysql用户添加

一、连接mysql服务 mysql -u root -p 二、查询用户表 use mysql &#xff1b; SELECT User, Host FROM mysql.user; 三、新增用户并授权 Create USER dev4rw% IDENTIFIED WITH mysql_native_password BY 新密码; GRANT ALL PRIVILEGES ON *.* TO dev4rw% WITH GRANT OP…...

628. 三个数的最大乘积

628. 三个数的最大乘积 class Solution {public int maximumProduct(int[] nums) {Arrays.sort(nums); return Math.max(nums[nums.length-1]*nums[nums.length-2]*nums[nums.length-3],nums[0]*nums[1]*nums[nums.length-1]);} }...

linux驱动开发入门(学习记录)

2023.7.6及7.7 概述了解 一 1.驱动框架 2. 字符设备 块设备&#xff0c;存储相关 网络设备驱动 不一定属于某一种类型二 1.获取外设或传感器数据&#xff0c;控制外设&#xff0c;数据会提交给应用程序 2.编写一个驱动&#xff0c;及测试应用程序 app。驱动和应用完全分开 3.驱…...

SpringCloud-Alibaba之Sentinel熔断与限流

一、下载安装运行 http://localhost:8080进行访问 登录账号和密码均为sentinel 二、创建工程&#xff0c;并注册到nacos服务中心 依赖spring-cloud-starter-alibaba-nacos-discovery,spring-cloud-starter-alibaba-sentinel sentine-datasource-nacos (持久化)配置文件 se…...

深“扒”云原生高性能分布式文件系统JuiceFS

JuiceFS 是一款面向云原生设计的高性能分布式文件系统&#xff0c;在 Apache 2.0 开源协议下发布。提供完备的 POSIX 兼容性&#xff0c;可将几乎所有对象存储接入本地作为海量本地磁盘使用&#xff0c;亦可同时在跨平台、跨地区的不同主机上挂载读写。 JuiceFS 简介 JuiceFS…...

opencv-18 什么是色彩空间?

1.什么是色彩空间类型&#xff1f; 色彩空间类型&#xff0c;也称为颜色空间类型或色彩模型&#xff0c;是一种表示图像中颜色的方式。在计算机图形学和数字图像处理中&#xff0c;有许多种色彩空间类型&#xff0c;每种类型有不同的表达方式和特点。 常见的色彩空间类型包括&a…...

RedHat离线安装工具yum+gcc+pcre+zlib+openssl+openssh

RedHat离线安装工具yumgccpcrezlibopensslopenssh 【一】安装gcc-c&#xff08;解决yum不可用问题&#xff09;&#xff08;1&#xff09;问题描述&#xff08;2&#xff09;替换安装yum&#xff08;3&#xff09;安装gcc 【二】安装pcre【三】安装zlib【四】安装openssl【五】…...

Redis概述及安装、使用和管理

目录 一、NoSQL非关系型数据库 1.NoSQL概述 2.关系型数据库和非关系型数据库区别 &#xff08;1&#xff09;数据存储方式不同 &#xff08;2&#xff09;扩展方式不同 &#xff08;3&#xff09;对事务性的支持不同 3.非关系型数据库使用场景 二、Redis概述 1.简介 2…...

【算法第十一天7.25】二叉树前、中、后递归、非递归遍历

链接&#xff1a;力扣94-二叉树中序遍历 链接&#xff1a;力扣144-二叉树前序遍历 链接&#xff1a;力扣145-二叉树后序遍历 树的结构 * public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { thi…...

Linux搭建Promtail + Loki + Grafana 轻量日志监控系统

一、简介 日志监控告警系统&#xff0c;较为主流的是ELK&#xff08;Elasticsearch 、 Logstash和Kibana核心套件构成&#xff09;&#xff0c;虽然优点是功能丰富&#xff0c;允许复杂的操作。但是&#xff0c;这些方案往往规模复杂&#xff0c;资源占用高&#xff0c;操作苦…...

[PyTorch][chapter 44][RNN]

简介 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类以序列&#xff08;sequence&#xff09;数据为输入&#xff0c;在序列的演进方向进行递归&#xff08;recursion&#xff09;且所有节点&#xff08;循环单元&#xff09;按链式连接的递归神经网…...

20230726----重返学习-vue3项目实战-知乎日报第3天-TS-简历

day-121-one-hundred-and-twenty-one-20230726-vue3项目实战-知乎日报第3天-TS-简历 vue3项目实战-知乎日报第3天 封装按钮组件 jsx函数式组件 只能做静态页面&#xff0c;内部没有方法让它自动更新。 封装第三方按钮-非计算属性版 封装第三方按钮-不使用计算属性 src/c…...

TypeScript 在前端开发中的应用实践

TypeScript 在前端开发中的应用实践 TypeScript 已经成为前端开发领域越来越多开发者的首选工具。它是一种静态类型的超集&#xff0c;由 Microsoft 推出&#xff0c;为开发者提供了强大的静态类型检查、面向对象编程和模块化开发的特性&#xff0c;解决了 JavaScript 的动态类…...

商业密码应用安全性评估量化评估规则2023版更新点

《商用密码应用安全性评估量化评估规则》&#xff08;2023版&#xff09;已于2023年7月发布&#xff0c;将在8月1日正式执行。相比较2021版&#xff0c;新版本有多处内容更新&#xff0c;具体包括5处微调和5处较大更新。 微调部分&#xff08;5处&#xff09; 序号2021版本202…...

【软件测试】单元测试工具---Junit详解

1.junit 1.1 junit是什么 JUnit是一个Java语言的单元测试框架。 虽然我们已经学习了selenium测试框架&#xff0c;但是有的时候测试用例很多&#xff0c;我们需要一个测试工具来管理这些测试用例&#xff0c;Junit就是一个很好的管理工具&#xff0c;简单来说Junit是一个针对…...

【算法基础:搜索与图论】3.4 求最短路算法(Dijkstrabellman-fordspfaFloyd)

文章目录 求最短路算法总览Dijkstra朴素 Dijkstra 算法&#xff08;⭐原理讲解&#xff01;⭐重要&#xff01;&#xff09;&#xff08;用于稠密图&#xff09;例题&#xff1a;849. Dijkstra求最短路 I代码1——使用邻接表代码2——使用邻接矩阵 补充&#xff1a;稠密图和稀疏…...

【Matlab】基于卷积神经网络的数据分类预测(Excel可直接替换数据)

【Matlab】基于卷积神经网络的数据分类预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码6.完整代码7.运行结果1.模型原理 基于卷积神经网络(Convolutional Neural Network,CNN)的数据分类预测是一种常见的深度学习方法,广泛应用于图像识…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...