不讲协议,只讲怎么用。
ndef数据主要分为几个部分;
分为头,type长度(类型,也就是type占几个字节),pyload长度(数据,也就是数据占几个字节),type数据,type进一步分类,pyload数据。
整体的数据结构如下:
Bit 7 6 5 4 3 2 1 0
第一字节:[ MB ][ ME ][ CF ][ SR ][ IL ][ TNF ]
第二字节:[ TYPE LENGTH ]
第三字节:[ PAYLOAD LENGTH ]
第四字节:[ ID LENGTH ]
.......................TYPE .......................
........................ID.........................
..................... PYLOAD.......................
举例说明:
加入想要写的文本为 hello word!
0xd1
0x01
0X0d
0X54
0x7a 0x68
0x68 , 0x65 ,0x6c , 0x6c ,0x6f , 0x20 , 0x77 ,0x6f , 0x72 ,0x64 , 0xef ,0xbc , 0x81
首先介绍第一字节:
0xd1 (1101 0001)
bit 0:MB = 1 表明这是NDEF消息的第1个记录
bit 1:ME = 1 表明这是NDEF消息的最后一个记录,如果 ME = 0,后面还有记录
bit 2:CF = 0 表明这不是分块消息
bit 3: SR = 1 表明内容长度域是一个八位组。短记录的布局是用来为长度不到255个八位组的内容做精简封装
bit 4: IL = 1,则 ID_LEN 域出现在头部,长度为1个八位组。如果 IL = 0,ID_LEN 域就从记录头部忽略
bit 5-7: TNF 指示了 TYPE 域值的结构。0x01这个值是NFC论坛已知值
type长度:
0x01
pyload长度:
0X0d
ID长度: 忽略
type(1 bit):
0X54 (T)
ID:忽略
文本进一步描述
0x7a 0x68
TYPE(进一步分类):
pload: (hello word! )
0x68 , 0x65 ,0x6c , 0x6c ,0x6f , 0x20 , 0x77 ,0x6f , 0x72 ,0x64 , 0xef ,0xbc , 0x81
上代码
定义结构体类型
// NDEF NTF类型
typedef enum{
TNF_NULL = 0, // 空
TNF_INSIDE_RTD = 1, // NFC 论坛知名类型,包括UTF8、ASCII、URI...
TNF_RFC2406 = 2, // 定义于RFC 2046[RFC 2046]的媒体类型
TNF_RFC3986 = 3, // 定义于 RFC 3986[RFC 3986]的绝对 URI
TNF_OUTSIDE_RTD = 4, // NFC 论坛外部自定义类型
TNF_UNKNOW = 5, // 未知
TNF_STATIC = 6, // 不可更改(参考2.3.3节)
TNF_DEFAULT = 7 // 保留
} TnfType;
// NDEF TNF_INSIDE_RTD类型
typedef enum{
RTD_UTF8 = 'T', // UTF8类型
RTD_URI = 'U', // URI类型
} RtdType;
typedef enum{
START_PACK, // 分包开始包
MIDDLE_PACK, // 分包中间包
END_PACK, // 分包结束包
START_END_PACK // 不分包,开始包也是结束包
}PackType;
// NDEF URI
typedef enum{
RTD_URI_freeForm, // 0x00 No prepending is done ... the entire URI is
// contained in the URI Field
RTD_URI_httpWWW, // 0x01 http://www.
RTD_URI_httpsWWW, // 0x02 https://www.
RTD_URI_http, // 0x03 http://
RTD_URI_https, // 0x04 https://
RTD_URI_tel, // 0x05 tel:
RTD_URI_mailto, // 0x06 mailto:
RTD_URI_ftpAnonymous, // 0x07 ftp://anonymous:anonymous@
RTD_URI_ftpFtp, // 0x08 ftp://ftp.
RTD_URI_ftps, // 0x09 ftps://
RTD_URI_sftp, // 0x0A sftp://
RTD_URI_smb, // 0x0B smb://
RTD_URI_nfs, // 0x0C nfs://
RTD_URI_ftp, // 0x0D ftp://
RTD_URI_dav, // 0x0E dav://
RTD_URI_news, // 0x0F news:
RTD_URI_telnet, // 0x10 telnet://
RTD_URI_imap, // 0x11 imap:
RTD_URI_rtps, // 0x12 rtsp://
RTD_URI_urn, // 0x13 urn:
} UriVal;
// NDEF首字节解码
typedef struct{
unsigned char TNF : 3; // TNF标志是 3-bit 字段,指示TYPE字段值的结构
unsigned char IL : 1; // IL 标志是 1-bit 字段,置 1 表示在首部存在一个单字节ID_LENGTH字段
unsigned char SR : 1; // SR 标志是 1-bit 字段,置 1 表示PAYLOAD_LENGTH字段为单字节
unsigned char CF : 1; // CF 标志是 1-bit 字段,置 1 表示 NDEF 消息分块传输
unsigned char ME : 1; // ME 标志是 1-bit 字段,置 1 表示 NDEF 消息的结束
unsigned char MB : 1; // MB 标志是 1-bit 字段,置 1 表示 NDEF 消息的开始
} NdefHead;
// NDEF 参数 文本类结构体
typedef struct{
PackType packtype; //是否分包
RtdType dataType; //数据类型
UriVal uriVal; //uri类型
} NdefFrame;
ndef制作
/** application/vnd.wfa.wsc[23]=0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,0x76,0x6e,0x64,0x2e,0x77,0x66,0x61,0x2e,0x77,0x73,0x63
* @brief NDEF包制作函数
* @param ndef 传入NDEF相关参数
* @param mem 保存根据NDEF参数制作的NDEF数据
* @return 返回TRUE表示NDEF数据制作成功
*/
BOOL TWNdefPackMake(NdefFrame *ndef, MemFrame *mem)
{
if (ndef->payloadLen > NDEF_RECORD_SIZE) //数据超出存储范围
{
return FALSE;
}
switch (ndef->packtype)
{
case START_PACK:
mem->data[0] = 0x91;
break;
case MIDDLE_PACK:
mem->data[0] = 0x11;
break;
case END_PACK:
mem->data[0] = 0x51;
break;
case START_END_PACK:
mem->data[0] = 0xD1;
break;
default:
return FALSE;
}
mem->data[1] = 0x01;
switch (ndef->dataType)
{
case RTD_UTF8:
ndef->payloadLen += 3;
break;
case RTD_URI:
ndef->payloadLen += 1;
break;
default:
return FALSE;
}
mem->data[2] = ndef->payloadLen; // PLlen
mem->data[3] = ndef->dataType; // type
mem->len = ndef->payloadLen + 4;
if (ndef->dataType == RTD_UTF8)
{
mem->data[4] = 2;
mem->data[5] = 'z';
mem->data[6] = 'h';
memcpy(&mem->data[7], ndef->payload, ndef->payloadLen);
}
else
{
mem->data[4] = ndef->uriVal;
memcpy(&mem->data[5], ndef->payload, ndef->payloadLen);
}
return TRUE;
}
ndef解析
/**
* @brief NDEF包解析函数
* @param ndef 保存解析后的NDEF相关参数
* @param mem 被解析的NDEF数据
* @return 返回TRUE表示NDEF数据解析成功
*/
BOOL TWNdefPackParsing(NdefFrame *ndef, unsigned char *mem)
{
NdefHead head;
memcpy(&head, &mem[0], 1);
ndef->payloadLen = mem[2];
if (ndef->payloadLen > NDEF_RECORD_SIZE) //数据域过长
{
return FALSE;
}
ndef->dataType = mem[3];
unsigned char type = (head.MB << 2) | (head.ME << 1) | head.CF;
switch (type) //分包类型
{
case 0:
ndef->packtype = MIDDLE_PACK;
break;
case 2:
ndef->packtype = END_PACK;
break;
case 4:
ndef->packtype = START_PACK;
break;
case 6:
ndef->packtype = START_END_PACK;
break;
default:
return FALSE;
}
if (ndef->dataType == RTD_UTF8)
{
ndef->payloadLen -= 3;
memcpy(ndef->payload, &mem[4 + 3], ndef->payloadLen);
}
else
{
ndef->uriVal = mem[4];
ndef->payloadLen -= 1;
memcpy(ndef->payload, &mem[4 + 1], ndef->payloadLen);
}
ndef->dataType = 1;
return TRUE;
}
以后更新,碰一碰实现打开APP,碰一碰WiFi配网等功能。
如有错误,请多多指正