解决方案:【STM32 x ESP8266】连接 MQTT 服务器(报文,附部分源码解析)
优采云 发布时间: 2022-11-21 13:28解决方案:【STM32 x ESP8266】连接 MQTT 服务器(报文,附部分源码解析)
MQTT协议是物联网非常重要的传输协议。如何使用它非常重要。不懂的可以点这里学习。这里只是简单介绍一下。同时,这里附上MQTT 3.1.1协议中文版pdf链接。对协议底层感兴趣的同学可以下载研究。同时,基于该消息实现了以下实现功能。
在这里整体下载工程(赚积分),查看消息和调试不易,请多多支持。本项目是在Wildfire的3-上传DHT11温湿度到电脑网络助手的基础上,增加了MQTT部分,主要使用里面的TCP连接+透传设置。
示例功能:通过stm32控制esp8266连接阿里云MQTT服务器/自己服务器搭建的MQTT服务器
服务器(如 EMQ)/其他公共 MQTT 服务器。用户只需要在mqtt_config.h文件中修改MQTT服务器的相关信息即可。
关于如何连接阿里云MQTT服务器的内容在这篇文章中。有需要的可以去看看怎么用。
开发版:野火指南+内置ESP8266
ESP8266要求:使用原装固件,无需烧录专门连接MQTT服务器的固件
一、MQTT协议消息标识 1、CONNECT连接消息 1.1 Client ID
ClientId 是 MQTT 客户端的标识。MQTT 服务器使用此标识符来识别客户端。所以ClientId必须是独立的。如果两个 MQTT 客户端使用相同的 ClientId,则服务器会将它们视为同一客户端。
1.2 清除会话
① 如果不设置此标志(cleanSession = "false" && QoS > 0),服务器会保存未被客户端确认的消息,并再次尝试向客户端发送消息,等待客户端再次发送 确认信息。
②如果设置了这个标志(cleanSession = "true"),服务器不需要客户端确认收到消息,也不会保存任何消息。在这种情况下,即使客户端错过了服务器发送的消息,服务器也没有办法再次发送消息。
1.3 心跳间隔
让客户端在没有向服务器发送信息的时候定时向服务器发送消息。心跳请求的作用是通知服务器当前客户端还在线。
例如,如果心跳间隔为 60 秒。那么,如果服务器在90秒内没有收到客户端发出的消息或者心跳请求(PINGREQ)请求,那么就会认为客户端下线了。
2. PUBLISH 发布消息消息 1.1 保留标志
默认情况下,当客户端订阅一个主题时,它不会立即收到有关该主题的信息。只有当客户端订阅了主题,服务端收到主题的新信息后,服务端才会将最新收到的主题信息推送给客户端。
但在某些情况下,我们需要客户端在订阅某个主题后立即收到一条关于该主题的信息。这时候就需要reserved flag的信息了。
每个topic只能有一条“reserved message”,如果client要更新“reserved message”,需要向topic发送一条新的“reserved message”,这样服务器会覆盖掉新的“reserved message”保留消息”。
如果你想删除一个主题的“保留消息”,你可以**向该主题发布一个空的“保留消息”**。
1.2 QoS——服务质量等级
QoS = 0 –> 最多发送一次
QoS = 1 –> 至少发送一次
QoS = 2 –> 保证接收一次
① QoS = 0 -> 最多发送一次
QoS = 0 时,MQTT 协议不保证所有消息都能传输。也就是说,MQTT服务端和客户端不会确认和检查消息是否发送成功。消息能否成功传输取决于网络环境是否稳定。发件人不检查发送的消息是否可以正确接收。
② QoS = 1 –> 至少发送一次
发送方将消息发送给接收方后,将等待接收方的确认。接收端成功收到消息后,会向发送端发送确认消息PUBACK。如果发送方收到这个PUBACK确认消息,就知道消息已经接收成功。
如果一段时间后,发送方没有收到PUBACK报文,发送方会再次发送报文,然后再次等待接收方的PUBACK确认报文。因此,当QoS = 1时,发送方在收到接收方的PUBACK确认报文之前,会重复发送相同的报文。
③ QoS = 2 –> 保证接收一次
QoS = 2 的*敏*感*词*相对更复杂。发送方需要接收方的两次消息确认。因此,MQTT QoS 级别 2 是最安全的服务级别,也是最慢的。
接收方收到QoS = 2消息后,会返回一个PUBREC消息作为响应。发送方收到 PUBREC 消息后,会将消息存储起来,并返回一条 PUBREL 消息作为响应。当接收端收到PUBREL消息后,会回复一个PUBCOMP消息给发送端。至此,一个QoS2 MQTT消息传输就结束了。
3. 意志
一旦客户端意外断开连接,服务器可以将客户端的意愿公布于众。
遗嘱收录
遗嘱主题、遗嘱信息、遗嘱QoS、遗嘱保留。
3.1 遗嘱操作建议
假设我们现在有一个 MQTT 客户端。它的客户端 ID 是 client-1。它的遗嘱主体是“client-1-will”。
当client-1连接到服务器时,CONNECT消息中的will消息是“offline”。它已将遗嘱认证设置为真。
当 client-1 成功连接到服务器后,它立即向遗嘱主题“client-1-will”发布一条“online”消息。此外,在发布此消息时,保留标志设置为 true。这样只要client-1在线,任何订阅“client-1-will”的设备都可以收到设备在线的“online”消息。
如果 client-1 意外下线。然后只要任何设备订阅了“client-1-will”,它就会收到设备离线的消息“offline”。
如果 client-1 恢复连接,那么它会将遗嘱主题“client-1-will”的保留消息更改为“online”,这样任何订阅“client-1-will”的设备都会收到消息设备在线“在线”。
二、项目分析
注:本项目实践对象为自己搭建的MQTT服务器EMQ。如何连接阿里云MQTT服务器的内容在这篇文章中。有需要的可以去看看怎么用。
1、ESP8266连接WIFI+连接MQTT服务器
bsp_esp8266_test.h
/********************************** 用户需要设置的参数**********************************/
#define macUser_ESP8266_ApSsid "" //要连接的热点的名称
#define macUser_ESP8266_ApPwd "" //要连接的热点的密钥
#define macUser_ESP8266_TcpServer_IP IP //要连接的服务器的 IP(在 mqtt_config.h 中定义)
#define macUser_ESP8266_TcpServer_Port PORT //要连接的服务器的端口(在 mqtt_config.h 中定义)
2. mqtt_config.h 2.1 切换连接其他MQTT服务器
#define USE_Aliyun_MQTT 0 // 是否使用阿里云的免费MQTT服务器
2.2调试开关
#define DEBUG_1 1 // 为 0 屏蔽内部所有串口输出信息
#define DEBUG_2 1 // 查看接收/发送的报文
2.3 修改缓冲区大小
#define MAX_BUF_SIZE 2048 // 接收/发送的数据缓冲区
#define MAX_THEME_NUM 10 // 最大存储订阅主题数目
2.4 移植需要提供什么
#define Rx_Finish_Flag strEsp8266_Fram_Record.InfBit.FramFinishFlag // 串口接收完成标志
#define Rx_Buffer strEsp8266_Fram_Record.Data_RX_BUF // 串口接收缓冲区
#define Rx_Buffer_Len strEsp8266_Fram_Record.InfBit.FramLength // 串口接收数据长度
#define ESP8266_USART macESP8266_USARTx // ESP8266的串口
/*
提供一个能够准确计算一长串16进制数据的长度的函数(strlen函数有些情况统计的长度要比实际长度小)
函数格式:int UpdateStrlen_uint8_t(const void* source),函数返回值是实际长度值(该函数在my_string.c中)
*/
#define Count_Hex_Num(source) UpdateStrlen_uint8_t(source)
/*
提供发送报文函数,该函数要一个一个字节的接收
*/
#define Send_Message(usart, ch) Usart_SendByte(usart, ch)
2.5 用户详细配置MQTT连接参数
包括设置心跳周期,是否使用will,以及will的相关信息(阿里云MQTT服务器好像不能使用will,因为我一旦使用will,就不会连接我返回消息),设置ClientID,决定是否匿名登录(阿里云MQTT服务器只能使用账号和密码登录)
#define Set_KeepAlive 60 // 设置心跳周期
#if(USE_Aliyun_MQTT == 1) /* 使用阿里云MQTT服务器 */
#define Enable_Will_Topic 0 // 阿里云MQTT服务器应该是不能使用遗嘱的,置 0
#define ClientID "zyt" // 自定义
#define Enable_Username_And_Password 1 // 必须置 1,不能置零!!!
#else /* USE_Aliyun_MQTT == 0 使用其他的MQTT服务器 */
#define Enable_Will_Topic 1 // 是否使用遗嘱主题
#define MQTTClientID "zyt" // 自定义
#define Enable_Username_And_Password 1 // 是否使用用户名密码,有些MQTT服务器支持匿名登录
#endif /* USE_Aliyun_MQTT */
#if (Enable_Will_Topic == 1) /* 使用遗嘱主题 */
#define Will_Topic_Qos Qos1 // 遗嘱主题 Qos 等级
#define Will_Topic_Name "/user/will"// 遗嘱主题名字
#define Will_Topic_Message "off_line" // 遗嘱主题的消息内容
#endif /* Enable_Will_Topic */
3.mqtt.h
该定义用在void MQTT_ReceiveMsg(u8 mqtt_msg_type, u8 *mqtt_rxbuf)函数中,主要是为了区分不同发送消息的返回消息长度,详见下文。
不要修改这个定义!!
/* ========================== MQTT报文类型 ========================== */
#define MQTT_TypeCONNECT 1 //请求连接
#define MQTT_TypeCONNACK 2 //请求应答
#define MQTT_TypePUBLISH 3 //发布消息
#define MQTT_TypePUBACK 4 //发布应答
#define MQTT_TypePUBREC 5 //发布已接收,保证传递1
#define MQTT_TypePUBREL 6 //发布释放,保证传递2
#define MQTT_TypePUBCOMP 7 //发布完成,保证传递3
#define MQTT_TypeSUBSCRIBE 8 //订阅请求
#define MQTT_TypeSUBACK 9 //订阅应答
#define MQTT_TypeUNSUBSCRIBE 10 //取消订阅
#define MQTT_TypeUNSUBACK 11 //取消订阅应答
#define MQTT_TypePINGREQ 12 //ping请求
#define MQTT_TypePINGRESP 13 //ping响应
#define MQTT_TypeDISCONNECT 14 //断开连接
#define MQTT_WriteMsg 15 //等待接收订阅的消息(自定义的)
这些宏定义是设置CONNECT连接消息的标志位和遗嘱主题的设置。如果不需要使用遗嘱,只需要将MQTT_StaWillFlag设置为0,与遗嘱相关的内容就会失效。不使用用户名和密码也是一样的操作,只需将 MQTT_StaUserNameFlag 和 MQTT_StaPasswordFlag 设置为 0 即可。
CONNECT连接报文的内容可以根据您的实际需要进行更改,CONNACK报文的返回码不能更改。
/* ========================== CONNECT报文设置 ========================== */
#define MQTT_StaCleanSession 1 //清理会话
#define MQTT_StaWillFlag 1 //遗嘱标志
#define MQTT_StaWillQoS 0 //遗嘱QoS连接标志的第4和第3位。
#define MQTT_StaWillRetain 0 //遗嘱保留
#define MQTT_StaUserNameFlag 1 //用户名标志 User Name Flag
#define MQTT_StaPasswordFlag 1 //密码标志 Password Flag
#define MQTT_KeepAlive 120 //心跳周期
#define MQTT_ClientIdentifier "111" //客户端标识符 Client Identifier
#define MQTT_WillTopic "yizhu" //遗嘱主题 Will Topic
#define MQTT_WillMessage "zheshiyizhu" //遗嘱消息 Will Message
#define MQTT_UserName "zyt" //用户名 User Name
#define MQTT_Password "010823" //密码 Password
/* ========================== CONNACK报文返回码 ========================== */
#define Connect_Accept 0x00 // 连接已接受
#define Connect_Refuse_Version 0x01 // 连接已拒绝,不支持的协议版本
#define Connect_Refuse_ClientId 0x02 // 连接已拒绝,不合格的客户端标识符
#define Connect_Refuse_Sever_Unavailable 0x03 // 连接已拒绝,服务端不可用
#define Connect_Refuse_Acc_Or_Pass 0x04 // 连接已拒绝,无效的用户名或密码
4. mqtt.c 4.1 生成MQTT消息的固定头函数:GetDataFixedHead()(用户无需调用)
该函数在生成消息时使用,用户层不需要调用该函数。
remaining剩余长度的值与每条消息的长度有关,所以这部分通常在最后生成,由static int AddRemainingLength(void* mqtt_txbuf, uint8_t cps_len)函数负责。
/**
* @brief 生成固定报头
*
* @param MesType: mqtt报文类型(详见mqtt.h)
* @param DupFlag: 重发标志
* @arg 0: 客户端或服务端第一次请求发送这个报文
* @arg 1: 可能是一个早前报文请求的重发
* @param QosLevel: Qos等级
* @param Retain: 保留标志(设置后在订阅了该主题后马上接收到一条该主题的信息)
* @arg 0: 不发布保留消息
* @arg 1: 发布保留消息
*
* @retval 返回固定报头(8bit/1位)
*/
uint8_t GetDataFixedHead(unsigned char MesType, unsigned char DupFlag, unsigned char QosLevel, unsigned char Retain)
{
unsigned char dat = 0;
dat = (MesType & 0x0f) > 4) == MQTT_TypePUBCOMP) // 处理报文标识符
return 0;
else
return -1;
}
4.6 发送心跳函数:MQTT_alive()
能够在心跳周期内发送一个心跳函数是非常重要的,因为这样可以让客户端和服务端知道对方是否因为某种原因异常断开连接(不是发送DISCONNECT消息断开),如果一个将连接到MQTT服务器时设置好,服务器会向已经订阅主题客户端的订阅者发送遗嘱。
同时客户端也可以知道自己已经和服务器断开了。这时,它可以通过重新连接来恢复连接。
#define MQTT_alive() SendPINGREQ()
/**
* @brief 发送心跳请求
*
* @param None
*
* @retval 0:与MQTT服务器通讯正常 -1:通讯可能断开,可以多发几次确认一下
*/
int SendPINGREQ(void)
{
mqtt_txbuf[0] = 0xc0;
mqtt_txbuf[1] = 0x00;
/* 发送 PINGREQ 报文 */
MQTT_SendMsg(mqtt_txbuf, 2);
/* 接收心跳响应报文 PINGRESP */
MQTT_ReceiveMsg(MQTT_TypePINGREQ, mqtt_rxbuf);
if(Get_Fixed_Header_Type(mqtt_rxbuf) == MQTT_TypePINGRESP)
return 0;
else
return -1;
}
4.7 半覆盖遗嘱函数:MQTT_Modify_Will()
该功能的原理是再次向will主题发送一条新消息。
为什么叫“半覆盖”?具体原因请参考3.1遗嘱操作建议,此处不再赘述。
#if (MQTT_StaWillFlag == 1)
#define MQTT_Modify_Will(msg) MQTT_Publish_Topic(MQTT_WillTopic, msg, MQTT_StaWillQoS, Save_Msg)
#endif /*MQTT_alive()*/
4.8 *敏*感*词*订阅主题发送消息函数:MQTT_Listen_Topic()
该函数的作用是接收服务器发送的PUBLISH消息,根据提取的Qos等级判断是否需要发送回复消息。发送PUBREC、PUBCOMP、PUBACK消息的函数就不贴出来了,和之前的PUBREL类似。
接收完成后默认使用串口,在串口调试助手上显示接收到的报文(支持显示中文)。
#define MQTT_Listen_Topic() \
{ \
MQTT_ReceiveMsg(MQTT_WriteMsg, mqtt_rxbuf); \
PrintRecvMsg(); \
}
/**
* @brief 从esp8266获取到mqtt服务器返回的报文
*
* @param mqtt_msg_type: 在MQTT_SendMsg()函数中发送报文的类型(类型详见mqtt.h)
* @param mqtt_rxbuf: 存储从与esp8266连接的串口中暂存的报文
*
* @retval None
*/
void MQTT_ReceiveMsg(u8 mqtt_msg_type, u8 *mqtt_rxbuf)
{
u8 len = 0;
uint8_t qos;
uint16_t PBULISH_pid;
delay_nms(500);
/* 如果接收到了ESP8266的数据 */
if(strEsp8266_Fram_Record.InfBit.FramFinishFlag)
{
// 根据发送的报文类型得到接收到的报文长度
switch(mqtt_msg_type)
{
case MQTT_TypeCONNECT: // 返回报文类型是 CONNACK
case MQTT_TypePUBLISH: // 返回报文类型是 PUBACK/PUBREC
case MQTT_TypePUBREC: // 返回报文类型是 PUBREL
case MQTT_TypePUBREL: // 返回报文类型是 PUBCOMP
case MQTT_TypeUNSUBSCRIBE: // 返回报文类型是 UNSUBACK
len = 4;break;
case MQTT_TypeSUBSCRIBE: // 返回报文类型是 SUBACK
len = 5;break;
case MQTT_TypePINGREQ: // 返回报文类型是 PINGRESP
len = 2;break;
case MQTT_WriteMsg: // 等待接收订阅的消息
len = UpdateStrlen_uint8_t(strEsp8266_Fram_Record.Data_RX_BUF);break;
default:return;
}
memset(mqtt_rxbuf, 0, MAX_BUF_SIZE);
memset(buf, 0, MAX_BUF_SIZE);
#if ((DEBUG_1 == 1) && (DEBUG_2 == 1))
// 将接收到的报文显示在串口调试助手上
HexToAscii(strEsp8266_Fram_Record.Data_RX_BUF, buf, len, ADD_SPACE_AND_0X);
printf("接收报文: %s\n", buf);
#endif
// 将指定长度的报文保存至mqtt_rxbuf中
memcpy(mqtt_rxbuf, strEsp8266_Fram_Record.Data_RX_BUF, len);
// 函数接收到了订阅的主题发送过来的消息报文
if(mqtt_msg_type == MQTT_WriteMsg)
{
// 判断接收到的报文是什么类型的
switch(Get_Fixed_Header_Type(mqtt_rxbuf))
{
// 接收到 PUBLISH 报文
case MQTT_TypePUBLISH:
// 先保存发送过来的消息内容
PBULISH_pid = Get_Packet_Identifier(mqtt_rxbuf, SaveReceiveBuf(len));
// 提取固定报头中的 qos 等级
qos = Get_Fixed_Header_Qos(mqtt_rxbuf);
// qos = 1:PUBLISH -> PUBACK
if(qos == 1)
SendPUBACK(PBULISH_pid);
// qos = 2:PUBLISH -> PUBREC PUBREL -> PUBCOMP
else if(qos == 2)
{
SendPUBREC(PBULISH_pid);
delay_nms(100);
SendPUBREC(PBULISH_pid);
delay_nms(100);
SendPUBCOMP(PBULISH_pid);
}
break;
default:break;
}
}
strEsp8266_Fram_Record.InfBit.FramLength = 0; //接收数据长度置零
strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0; //接收标志置零
memset(strEsp8266_Fram_Record.Data_RX_BUF, 0, RX_BUF_MAX_LEN); // 清空数据缓冲区
}
}
#if (DEBUG_1 == 1)
void PrintMsg(void)
{
// 打印接收到的消息
for(int i = 0; i = 0xA1 )
{
printf("%c%c", themes[i].ThemeMsg[j], themes[i].ThemeMsg[j + 1]);
j += 2;
}
else
{
printf("%c", themes[i].ThemeMsg[j]);
j++;
}
}
printf("\n");
free(themes[i].ThemeMsg);
themes[i].ThemeMsg = NULL;
}
}
}
#endif
4.9 主动断开函数:MQTT_Disconnect()
#define MQTT_Disconnect() SendDISCONNECT()
/**
* @brief 发送断开连接的数据包
*
* @param mqtt_txbuf: 存储待发送报文的数组
*
* @retval None
*/
void SendDISCONNECT(void)
{
mqtt_txbuf[0] = 0xe0;
mqtt_txbuf[1] = 0x00;
/* 发送 DISCONNECT 报文 */
MQTT_SendMsg(mqtt_txbuf, 2);
}
三、实例演示 1、代码配置
这里发布了两个主题,一个是will主题,一个是“/user/123”主题。订阅了两个主题,一个是“/user/abc”,另一个是“/user/test”。
2、运行效果
解决方案:迅睿CMS开源内容管理框架(基于MIT开源协议) v4.10
迅锐CMS免费开源系统基于PHP8语言,采用最新的CodeIgniter4作为开发框架制作的网站内容管理框架,提供“电脑网站+手机网站+APP界面”一体化的网站技术解决方案。她拥有强大稳定的底层框架,基于灵活扩展的开发理念。二次开发方便,不破坏程序内核。为WEB美工打造的PHP建站程序,堪称PHP理财框架的万能建站框架。
迅锐CMS免费开源系统特点:
一、程序结构
迅锐CMS框架是采用PHP8新语法开发的网页内容管理系统开发框架。具有迅锐CMS强大的内容管理功能和内容管理系统灵活、可扩展的特点。堪称财务管理框架PHP通用建站框架。强大灵活的内容模块和插件机制,开发者可以自定义内容模块,也可以根据自己的需求以插件的形式进行扩展。&数字内容管理#13;
迅锐CMS框架采用最新的CodeIgniter4框架,内容管理系统二次开发文档齐全,并遵循框架原生的内容管理系统编程风格,非常方便风险管理框架的二次开发;CodeIgniter 安装包包括“用户手册”,手册包括框架组件的介绍、教程、“动手”说明和参考文档。
2 风险管理框架、效率和安全
1、使用PHP8新语法特性,设计时考虑性能优化,运行效率高达PHP5系列开发环境的4倍
2、利用CI框架的扩展性和路由模式,配合ZF框架强大丰富的中间件和扩展包,大大提高了迅锐CMS3系统的扩展性能;
3、Zend框架官方所有扩展包都支持免费引入本系统,按需加载模式最大化开发效率
4.利用ZF提供的安全旗内容管理相关组件,包括SQ内容管理系统L注入、XSS、CSRF、垃圾邮件和密码暴力破解攻击
5、动态缓存技术,可以在动态旗帜的内容管理页面中加入缓存,使得采用动态页面方式的网络数字内容管理站访问速度更快、效率更高
6、全站支持FineCMS支持HTTPS传输协议,更安全,支持小程序数据请求的URL规范FineCMS3;
7、表单增加“csrf_token”验证功能,保护更强
3、多插件机制
框架采用多个Module作为管理框架pp应用,迅锐CMS沿用了这一设计模式,支持多App插件。
1、插件目录结构:大风风控框架yrui/App/***/。
2、插件支持独立运行。
3.插件内部结构锦旗内容管理遵循CI4App管理框架规则。
四、自定义CI内容管理扩展类
迅锐CMS在不破坏CI4框架本身的情况下,扩展了CI自带的类库。
1.重写CI错误异常显示类,本地化。数字内容管理
2、重写路由类,使其符合国内建站程序的URL结构,如:c=controller&m=method name&id=parameter。
3.重写钩子类。CI4 挂钩类将在所有应用程序中加载自定义挂钩。pps太多的理财框架会影响速度。迅锐CMS提出了一个全局的hook配置文件。
4.重写安全类,加强对非法字符串的过滤。
5.模板解析类(查看)
" />
CI4本身的模板解析类不是很灵活。迅锐CMS采用天锐自主研发的天锐模板引擎技术。MVC设计模式实现了业务逻辑和表现层的恰当分离。迅锐CMS让网页设计师轻松设计出理想的模板。
1.支持原生PHP语法特性。
2.支持CI框架语法结构。
3. {Variable} 自定义系统中数字内容管理标签的语法结构。
4、模板缓存只需要解析一次,提高性能。
6.FineCMS自定义扩展类目录
迅锐CMS有一个全局的Library目录,专门用来扩展类库的。它和Librarys不一样,但是原来的风险管理框架是一样的。
1. 全局库调用。
2.可以继承全局Library函数类。
3、App有自己独立的Library函数类。
4、跨App支持调用任意App的Librar三角旗内容管理功能类。
七、网站模板机制
CI管理框架4没有终端识别模式,迅锐CMS增加了多终端识别和自定义终端显示。
1.迅财务管理框架瑞CMS模板分为移动端和电脑端。
2.可以直接在后台编辑网站模板和手机模板。
3.编辑模板自动备份,避免旧模板丢失。
4、自动锦旗内容管理在编辑模板时检查模板语法是否正确。
5. 用中文命名模板文件,避免快速区分。
八、通用表类
迅锐CMS框架为开发者准备了一个万能的Table类。该类用于对数据表进行增删改查操作。只有内容管理系统需要配置文件,迅锐CMS帮您完成逻辑功能。
1.支持任意表格数据展示。
2.多表联合查询。
3.自定义字段格式存储规则。
九、自定义字段
迅锐CMS采用了非常成熟的自定义字段解决方案,可以支持对栏目表自定义字段、内容表自定义字段、表单表自定义字段、用户表自定义字段、评论表自定义字段、页面表自定义字段风险管理框架的数字化内容管理,链接表自定义字段、标签表自定义字段等
1. 文本字段,包括单行文本、多行文本和文本事件字段
" />
2.上传字段,有单文件上传和多文件上传
3.日期时间字段,财务管理框架支持自定义年月格式显示&FineCMS#13;
4. 联动菜单字段用于无限分类级别显示的数据,如城市
5.百度地图字段,用于定位地图坐标,过滤坐标范围内的数据
6、富文本字段、百度编辑器、百度手机编辑器
7、选项栏、单选栏、多选栏、下管理框拉选词内容管理系统段
8.color字段,用于选择网页的颜色值
9、属性字段,用于类似产品属性的数据
10、内容关联字段,用于添加锦旗内容管理加载其他模块内容字段,如专题内容管理系统功能
11 风险管理框架和价格字段用于CMF站点的购物交易,如文章买卖、下载收费等
12、单行分组字段,用于一行显示N个字段
12、多行分组字段,用于显示一个分组财务管理框内的N个字段
13.强大的DIY领域,这个领域比较强大,可以让开发者自己创建领域
迅锐CMS免费开源系统更新内容:
添加子管理锦旗内容管理员可添加管理员账号功能
在应用管理中添加应用直接入口
主域名变更时,栏目编辑器的域名将被联动替换
系统日志大于2MB时,财务管理框不显示网页内容
添加自定义字段类别:模块列(多选)
后台联动菜单列表显示数据量
优化联动菜单缓存算法,增加存储容量
图片剪辑财务管理框编辑界面加图片链接,方便查看图片内容管理系统;
优化列缓存,最大列数不再受限
重新定义栏目可用字段,内容管理控制不必要的栏目切换
管理架构
风险管理框架;