diff --git a/README.md b/README.md index 1f28118310dbdc8083ef342a0fad259485b972ac..27772049e0e64b1ee07f2256085e133360227386 100755 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ | TW305 | Network | udpserver | [UDP服务端联网演示](applications/app/TW305_Network_udpserver/README.md) | 核心板 | | TW305 | Network | udpclient | [UDP客户端联网演示](applications/app/TW305_Network_udpclient/README.md) | 核心板 | | TW306 | Network | httpclient | [HTTP客户端联网演示](applications/app/TW306_Network_httpclient/README.md) | 核心板 | +| TW401 | APP | wifi_nfc | [NFC碰一碰WiFi配网演示](applications/app/TW401_APP_wifi_nfc/README.md) | 核心板 + 底板+NFC扩展板 | | TW402 | APP | oled_u8g2 | [OLED U8G2库综合应用演示](applications/app/TW402_APP_oled_u8g2/README.md) | 核心板 + OLED扩展板| ## 五、源码目录简介 @@ -127,4 +128,3 @@ - diff --git a/applications/app/BUILD.gn b/applications/app/BUILD.gn index ef1e2be62e1b73ca19af2ccb19860143318b101e..5c29d0c4da14a7155295a95989a1d5aee35cf936 100755 --- a/applications/app/BUILD.gn +++ b/applications/app/BUILD.gn @@ -40,11 +40,12 @@ lite_component("app") { # "TW301_Network_wifista:network_wifista_example", # "TW302_Network_wifiap:network_wifiap_example", # "TW303_Network_mqttclient:network_mqttclient_example", - # "TW402_APP_oled_u8g2:app_oled_u8g2_example", # "TW304_Network_tcpserver:network_tcpserver_demo", # "TW304_Network_tcpclient:network_tcpclient_demo", # "TW305_Network_udpclient:network_udpclient_demo", # "TW305_Network_udpserver:network_udpserver_demo", # "TW306_Network_httpclient:network_httpclient_demo", + # "TW401_APP_wifi_nfc:app_wifi_nfc_example", + # "TW402_APP_oled_u8g2:app_oled_u8g2_example", ] } \ No newline at end of file diff --git a/applications/app/README.md b/applications/app/README.md index 413be4b2a04eea90314789b5244fbc184aa05a58..bacf6a53266919f991007d4d9c27432720858910 100755 --- a/applications/app/README.md +++ b/applications/app/README.md @@ -44,4 +44,5 @@ | TW305 | Network | udpserver | [UDP服务端联网演示](TW305_Network_udpserver/README.md) | 核心板 | | TW305 | Network | udpclient | [UDP客户端联网演示](TW305_Network_udpclient/README.md) | 核心板 | | TW306 | Network | httpclient | [http客户端联网演示](TW306_Network_httpclient/README.md) | 核心板 | +| TW401 | APP | wifi_nfc | [NFC碰一碰WiFi配网演示](TW401_APP_wifi_nfc/README.md) | 核心板 + 底板+NFC扩展板 | | TW402 | APP | oled_u8g2 | [OLED U8G2库综合应用演示](TW402_APP_oled_u8g2/README.md) | 核心板 + OLED扩展板| diff --git a/applications/app/TW401_APP_wifi_nfc/BUILD.gn b/applications/app/TW401_APP_wifi_nfc/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..ea190c6149d8f28b1895a7f2705a7b65964c503e --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2021 Talkweb Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("app_wifi_nfc_example") { + + sources = [ + "tw_wifi_sta.c", + "tw_wifi_nfc.c", + "tw_nfc_lib/adapter/tw_nfc_adapt.c", + "tw_nfc_lib/frameworks/tw_nfc_i2c.c", + "tw_nfc_lib/frameworks/tw_nfc_ndef.c", + "tw_nfc_lib/frameworks/tw_nfc.c", + ] + + include_dirs = [ + "//third_party/cJSON", + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/peripheral/interfaces/kits", + "//foundation/communication/wifi_lite/interfaces/wifiservice", + "//device/talkweb/niobe/sdk_liteos/third_party/lwip_sack/include", + "//applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/interfaces", + "//applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks", + "//applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter", + ] + +} diff --git a/applications/app/TW401_APP_wifi_nfc/README.md b/applications/app/TW401_APP_wifi_nfc/README.md new file mode 100755 index 0000000000000000000000000000000000000000..a11bb2b3098db3bf30f6190b1aa59e57b4cdacb9 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/README.md @@ -0,0 +1,101 @@ +# Niobe开发板NFC碰一碰WiFi配网 + +本案例程序将演示怎么在拓维Niobe开发板上,使用NFC扩展板实现碰一碰配网。 + +## 软件设计 + +### UML顺序图 + +![image-20220105170242091](figure/wifi-nfc-uml.png) + +**主要逻辑分析** + +开发板启动之后,程序会循环检测NFC标签内容,如果发现合法的wifi信息数据,使用wifi信息,连接指定的wifi。 + +1. Niobe开发板启动,碰一碰程序循环检测NFC标签内容是否拥有合法的wifi信息。 + +2. 使用带NFC功能的手机向NFC扩展板碰一碰,写入可用的wifi热点信息。 + +3. Niobe碰一碰程序检测到合法的wifi热点信息,启动wifi连接。 + +## 编译调试 + +### 修改 BUILD.gn 文件 + +修改 `applications/app/BUILD.gn` 路径中的 BUILD.gn 文件,指定 `app_wifi_nfc_example` 参与编译。 + +``` +# "TW305_Network_udpclient:network_udpclient_demo", +# "TW305_Network_udpserver:network_udpserver_demo", +# "TW306_Network_httpclient:network_httpclient_demo", +"TW401_APP_wifi_nfc:app_wifi_nfc_example", +# "TW402_APP_oled_u8g2:app_oled_u8g2_example", +``` + +### 运行结果 + +- 示例代码编译烧录代码后,按下开发板的RESET/SW2按键,启动碰一碰程序; + +- 连接串口工具,查看串口日志; + +- 使用带NFC功能的手机,向NFC扩展板写入可用的WiFi热点信息,写入数据必须是NDEF文本格式,数据格式为JSON,数据格式如下所示: + + ```json + {"ssid":"HUAWEI_B311_A741","pwd":"12345678"} + ``` + +- 串口日志运行如下: + + ```text + ready to OS start + + sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00 + + FileSystem mount ok. + wifi init success! + hilog will init. + hievent will init. + hievent init success. + hiview init success. + entry wifi nfc example. + + nfctag: {"ssid":"HUAWEI_B311_A741","pwd":"12345678"} + + wifi ssid: HUAWEI_B311_A741 , password: 12345678 + + RegisterWifiEvent errCode: 0 + + EnableWifi errCode: 0 + + AddDeviceConfig errCode: 0 + + ConnectTo(1) errCode: 0 + + No crash dump found! + + +NOTICE:SCANFINISH + +NOTICE:CONNECTED + OnWifiConnectionChanged 54, state = 1 + + info: bssid: A2:B9:EC:41:A7:C2, rssi: 0, connState: 0, reason: 0, ssid: HUAWEI_B311_A741 + + g_wifiState: 1 + + netifapi_dhcp_start: 0 + + server : + server_id : 192.168.26.1 + mask : 255.255.255.0, 1 + gw : 192.168.26.1 + T0 : 86400 + T1 : 43200 + T2 : 75600 + clients <1> : + mac_idx mac addr state lease tries rto + 0 20579e6185a4 192.168.26.116 10 0 1 2 + netifapi_netif_common: 0 + + The Niobe connect wifi success. + ``` + + diff --git a/applications/app/TW401_APP_wifi_nfc/figure/wifi-nfc-uml.png b/applications/app/TW401_APP_wifi_nfc/figure/wifi-nfc-uml.png new file mode 100755 index 0000000000000000000000000000000000000000..5d661e10d6f0ad4d87bb3c77dff0d31815df30c8 Binary files /dev/null and b/applications/app/TW401_APP_wifi_nfc/figure/wifi-nfc-uml.png differ diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/README.md b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/README.md new file mode 100755 index 0000000000000000000000000000000000000000..debcfe73c490daf5c05c469949fa2c4368fd1124 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/README.md @@ -0,0 +1,133 @@ +# tw_components_nfc_lite + +## nfc轻量系统工具包 + +此工具包实现了nfc读写标签的一些基本功能,使用的标准ndef格式。 + +## 基础环境构建 + +测试框架依赖于python运行环境,在使用测试框架之前可参阅以下方式进行配置。 + +- [环境配置](https://gitee.com/openharmony/docs/tree/master/zh-cn/device-dev/subsystems/subsys-testguide-envbuild.md) + +## 预备知识 + +### NDEF(NFC Data Exchange Format) + +NFC数据交换格式(NDEF)是一种标准化的数据格式,可用于在任何兼容的NFC设备和另一个NFC设备或标签之间交换信息。该数据格式由NDEF信息和NDEF记录组成。 + +NDEF格式用于存储和交换信息,如URI、纯文本等,使用一种普遍理解的格式。像一些NFC标签可被配置为NDEF标签,由一个NFC设备写入可以被任何其他NDEF兼容设备理解和访问的数据(NDEF记录)。 + +NDEF信息也可以用来在两个活跃的NFC设备之间以 "点对点 "模式交换数据。通过在通信过程中遵守NDEF数据交换格式,那些本来对彼此没有任何意义或共同语言的设备能够以一种有组织的、可相互 + +理解的方式分享数据。 + +NDEF消息是NDEF记录的基本 "运输 "机制,每个消息包含一个或多个NDEF记录。 + +### TLV + +为了使手机准确识别NFC标签信息,需要使用TLV格式。 + +TLV:Tag,Length,Value组成的数据单元。Tag一个字节,Length一个字节,然后是接着数据payload,数据长度和length一样。 + + +## 目录简介 + +以下是nfc轻量系统工具包框架的目录层级架构,在使用此框架过程中可在相应目录查找对应组件。 + +``` +nfc +├── adapter +├── frameworks +├── interfaces +├── test +├── BUILD.gn +└── README.md +``` + +### adapter:nfc工具库适配目录 + +#### adapter/tw_nfc_adapt: 底层适配文件 + +底层适配文件主要包含两部分: + +1. I2C接口的初始化和读写工作 + +2. 与NFC芯片相关的一些参数定义,包括NFC芯片地址、EEPROM起始地址、页大小等... + +### frameworks:核心框架代码存放目录 + +#### frameworks/tw_nfc_i2c: i2c读写NFC芯片的接口封装 + +主要API接口: + +1. I2C写NFC芯片EEPROM数据的功能函数: + + BOOL TWNfcI2CWriteMem(unsigned int addr, MemFrame *mem) + +2. I2C读NFC芯片EEPROM数据的功能函数: + + BOOL TWNfcI2CReadMem(unsigned int addr, unsigned int readSize, unsigned char *memBuf) + +#### frameworks/tw_nfc_ndef: nfc标准ndef格式相关函数 + +主要API接口: + +1. ndef包制作函数: + + BOOL TWNdefPackMake(NdefFrame *ndef, MemFrame *mem) + +2. ndef包解析函数: + + BOOL TWNdefPackParsing(NdefFrame *ndef, unsigned char *mem) + +#### frameworks/tw_nfc: nfc读写标签相关函数 + +主要API接口: + +1. 写nfc标签函数: + + BOOL TWNfcTagWrite(NdefFrame *param, unsigned char tagCnt) + +2. 读nfc标签函数: + + NdefParsingList *TWNfcTagRead(void) + +3. nfc读标签后的内存释放函数: + + void NfcReadTagFree(NdefParsingList *list); + + 注意: 读标签函数会使用malloc函数,请在处理完读取到的标签数据后,使用NfcReadTagFree()函数进行内存释放!!! + +### interfaces/tw_nfc_kits: API接口存放目录 + + 用户调用nfc工具包接口的头目录 + +### test:模块测试用例代码存放目录 + + 此目录中演示了如何使用nfc工具库进行标签的写入和读取。 + +### test/tw_nfc_readtag + + nfc标签读取功能的演示demo + +### test/tw_nfc_writetag + + nfc标签写入功能的演示demo + + 注意:当需要使用测试demo时,需在BUILD.gn文件中打开相关文件的编译选项 + +BUILD:模块编译文件 + +README:模块介绍文件 + +## 特别注意 + +此工具包暂时只支持以下ndef格式: + +1. 单个ndef record数据payload长度最大只支持256byte(默认为256byte),可在tw_nfc_ndef.h中修改定义 + +2. 只支持标准RTD格式中的UTF8数据格式和URI数据格式 + +3. 不支持带ID的ndef包格式 + diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter/tw_nfc_adapt.c b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter/tw_nfc_adapt.c new file mode 100755 index 0000000000000000000000000000000000000000..3b975708b8203f0162a83cf506733a8281bc4b9c --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter/tw_nfc_adapt.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tw_nfc_adapt.h" + +void TWNfcI2cInit(void) +{ + unsigned int ret = 0; + + IoTGpioInit(IOT_GPIO_IO_GPIO_13); + IoTGpioInit(IOT_GPIO_IO_GPIO_14); + + IoTIoSetPull(IOT_GPIO_IO_GPIO_13, IOT_IO_PULL_UP); + IoTIoSetPull(IOT_GPIO_IO_GPIO_14, IOT_IO_PULL_UP); + + IoTIoSetFunc(IOT_GPIO_IO_GPIO_13, IOT_IO_FUNC_GPIO_13_I2C0_SDA); + IoTIoSetFunc(IOT_GPIO_IO_GPIO_14, IOT_IO_FUNC_GPIO_14_I2C0_SCL); + + ret = IoTI2cInit(NFC_I2C_INDEX, 400000); + if (ret != IOT_SUCCESS) + { + printf("I2c Init failed 0, ret = %u\r\n", ret); + } + + // csn引脚 + IoTGpioInit(IOT_GPIO_IO_GPIO_9); + IoTIoSetFunc(IOT_GPIO_IO_GPIO_9, 0); + IoTIoSetPull(IOT_GPIO_IO_GPIO_9, IOT_IO_PULL_UP); + IoTGpioSetDir(IOT_GPIO_IO_GPIO_9, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_9, 0); +} + +int NfcI2cWrite(const unsigned char *data, unsigned int dataLen) +{ + osDelay(1); + unsigned int ret = IoTI2cWrite(NFC_I2C_INDEX, NFC_WRITE_ADDR, data, dataLen); + if (ret != IOT_SUCCESS) + { + osDelay(1); + ret = IoTI2cWrite(NFC_I2C_INDEX, NFC_WRITE_ADDR, data, dataLen); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cWrite fail 1, ret = %u\r\n", ret); + return IOT_FAILURE; + } + } + + return IOT_SUCCESS; +} + +int NfcI2cRead(const unsigned char *data, unsigned int dataLen) +{ + unsigned int ret = IoTI2cRead(NFC_I2C_INDEX, NFC_READ_ADDR, data, dataLen); + if (ret != IOT_SUCCESS) + { + osDelay(1); + ret = IoTI2cRead(NFC_I2C_INDEX, NFC_READ_ADDR, data, dataLen); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cRead fail 5, ret = %u\r\n", ret); + return IOT_FAILURE; + } + } + return IOT_SUCCESS; +} \ No newline at end of file diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter/tw_nfc_adapt.h b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter/tw_nfc_adapt.h new file mode 100755 index 0000000000000000000000000000000000000000..13d117d0fd1aa62ea470722ff76d96f3bef9ab34 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/adapter/tw_nfc_adapt.h @@ -0,0 +1,66 @@ +#ifndef _TW_WIFI_ADAPT_H +#define _TW_WIFI_ADAPT_H +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_i2c.h" +#include "iot_errno.h" +#include "iot_gpio.h" + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef BOOL +#define BOOL unsigned char +#endif + +// NFC I2C索引号 +#define NFC_I2C_INDEX IOT_I2C_IDX_0 + +// NFC 芯片地址 +#define NFC_ADDR 0xAE + +// NFC 芯片写地址 +#define NFC_WRITE_ADDR 0xAE + +// NFC 芯片读地址 +#define NFC_READ_ADDR 0xAF + +// NFC 芯片EEPROM 页大小 +#define NFC_PAGE_SIZE 16 + +// NFC 芯片EEPROM 开始地址 +#define NFC_EEPROM_ADDR_START 0X10 + +// NFC 芯片EEPROM 结束地址 +#define NFC_EEPROM_ADDR_END 0X387 + +// NFC 芯片EEPROM读写区域大小 +#define NFC_EEPROM_SIZE (NFC_EEPROM_ADDR_END - NFC_EEPROM_ADDR_START + 1) + +void TWNfcI2cInit(void); +int NfcI2cWrite(const unsigned char *data, unsigned int dataLen); +int NfcI2cRead(const unsigned char *data, unsigned int dataLen); + +#endif diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc.c b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc.c new file mode 100755 index 0000000000000000000000000000000000000000..46756f3351ac5407b38b4e7c946bc8d947519b4a --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tw_nfc.h" +#include + +/** + * @brief 写NFC标签函数 + * @param param 待写入的NFC标签信息 + * @param tagCnt 待写入的NFC标签个数 + * @return 返回TRUE表示写入NFC标签成功 + */ +BOOL TWNfcTagWrite(NdefFrame *param, unsigned char tagCnt) +{ + if (param == NULL) + { + printf("TWNfcTagWrite() param err!\r\n"); + return FALSE; + } + + if (tagCnt <= 0) + { + printf("TWNfcTagWrite() tagCnt <= 0!\r\n"); + return FALSE; + } + + MemFrame *memFrame = (MemFrame *)malloc(sizeof(MemFrame) * tagCnt); + if (memFrame == NULL) + { + printf("TWNfcTagWrite() malloc err!\r\n"); + return FALSE; + } + memset(memFrame, 0, sizeof(MemFrame) * tagCnt); + + // 获取TLV协议格式中的消息长度 + unsigned short tlvLen = 0; + for (unsigned int i = 0; i < tagCnt; i++) + { + if (TWNdefPackMake(¶m[i], &memFrame[i]) != TRUE) + { + printf("TWNdefPackMake() tagCnt[%u] err!\r\n", i); + free(memFrame); + return FALSE; + } + tlvLen += memFrame[i].len; + } + + unsigned int nfcStartAddr = 0; + MemFrame tlvHeadBuf = {0}; + tlvHeadBuf.data[0] = NFC_TLV_HEAD; + if (tlvLen > 255) + { + tlvHeadBuf.data[1] = 0xff; + tlvHeadBuf.data[2] = (unsigned char)(tlvLen >> 8) & 0xff; + tlvHeadBuf.data[3] = (unsigned char)(tlvLen >> 0) & 0xff; + tlvHeadBuf.len = 4; + nfcStartAddr = NFC_EEPROM_ADDR_START + 4; + } + else + { + tlvHeadBuf.data[1] = tlvLen; + tlvHeadBuf.len = 2; + nfcStartAddr = NFC_EEPROM_ADDR_START + 2; + } + + if (TWNfcI2CWriteMem(NFC_EEPROM_ADDR_START, &tlvHeadBuf) != TRUE) + { + printf("TWNfcI2CWriteMem() tlvHeadBuf err!\r\n"); + free(memFrame); + return FALSE; + } + + for (unsigned int i = 0; i < tagCnt; i++) + { + if (TWNfcI2CWriteMem(nfcStartAddr, &memFrame[i]) != TRUE) + { + printf("TWNfcI2CWriteMem() tagCnt[%u] err!\r\n", i); + free(memFrame); + return FALSE; + } + nfcStartAddr += memFrame[i].len; + } + + free(memFrame); + return TRUE; +} + +/** + * @brief 读NFC标签函数 + * @return 返回读取到的NFC标签链表头 + */ +NdefParsingList *TWNfcTagRead(void) +{ + unsigned char *memBuf = (unsigned char *)malloc(NFC_EEPROM_SIZE); + if (memBuf == NULL) + { + printf("TWNfcTagRead() malloc err!\r\n"); + return NULL; + } + memset(memBuf, 0, NFC_EEPROM_SIZE); + + TWNfcI2CReadMem(NFC_EEPROM_ADDR_START, NFC_EEPROM_SIZE, memBuf); + + if (memBuf[0] != NFC_TLV_HEAD) + { + printf("TWNfcTagRead() err: memBuf[0] != %02x \r\n", NFC_TLV_HEAD); + free(memBuf); + return NULL; + } + + unsigned int memLen = 0; + unsigned int startAddr = 0; + if (memBuf[1] == 0xff) + { + memLen = (memBuf[2] << 8) | memBuf[3]; + startAddr = 4; + } + else + { + memLen = memBuf[1]; + startAddr = 2; + } + + if (memLen > (NFC_EEPROM_SIZE - startAddr)) + { + printf("TWNfcTagRead() err: tlv memLen overflow, memLen = %u\r\n", memLen); + free(memBuf); + return NULL; + } + + NdefParsingList *head, *node, *end; + end = head = (NdefParsingList *)malloc(sizeof(NdefParsingList)); + while (startAddr <= memLen) + { + node = (NdefParsingList *)malloc(sizeof(NdefParsingList)); + end->next = node; + node->next = NULL; + end = node; + + if (TWNdefPackParsing(&node->ndef, &memBuf[startAddr]) != TRUE) + { + printf("TWNdefPackParsing() err\r\n"); + free(memBuf); + NfcReadTagFree(head); + return NULL; + } + startAddr += (node->ndef.payloadLen + 4); + startAddr += (node->ndef.dataType == RTD_UTF8) ? 3 : 1; + } + + free(memBuf); + return (NdefParsingList*)head; +} + +/** + * @brief 读NFC标签释放函数 + * @param list 待释放的NFC标签链表头 + */ +void NfcReadTagFree(NdefParsingList *list) +{ + NdefParsingList *p = list, *pr = NULL; + + while (p != NULL) + { + pr = p; + p = p->next; + free(pr); + } +} diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc.h b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc.h new file mode 100755 index 0000000000000000000000000000000000000000..39d4ae2819596adc059701c0efee18334bf5153a --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _TW_NFC_H +#define _TW_NFC_H +#include "tw_nfc_i2c.h" +#include "tw_nfc_ndef.h" + +/** + * @brief 写NFC标签函数 + * @param param 待写入的NFC标签信息 + * @param tagCnt 待写入的NFC标签个数 + * @return 返回TRUE表示写入NFC标签成功 + */ +BOOL TWNfcTagWrite(NdefFrame *param, unsigned char tagCnt); + +/** + * @brief 读NFC标签函数 + * @return 返回读取到的NFC标签链表头 + */ +NdefParsingList *TWNfcTagRead(void); + +/** + * @brief 读NFC标签释放函数 + * @param list 待释放的NFC标签链表头 + */ +void NfcReadTagFree(NdefParsingList *list); + +#endif diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_i2c.c b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_i2c.c new file mode 100755 index 0000000000000000000000000000000000000000..4669f2cf9787646c52afd201c9e7a6f298ab7997 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_i2c.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tw_nfc_i2c.h" + +/** + * @brief I2C写NFC EEPROM函数 + * @param addr 写入的EEPROM内存起始地址 + * @param mem 带写入的数据信息 + * @return 返回TRUE表示写入数据成功 + */ +BOOL TWNfcI2CWriteMem(unsigned int addr, MemFrame *mem) +{ + if (mem == NULL) + { + printf("TWNfcI2CWriteMem| mem is NULL\r\n"); + return FALSE; + } + + if (mem->len <= 0) + { + printf("TWNfcI2CWriteMem| mem dataLen <= 0\r\n"); + return FALSE; + } + + unsigned int ret = 0; + int dataLen = mem->len; + unsigned char *pData = mem->data; + unsigned short regAddr = addr; + unsigned char dataBuf[NFC_PAGE_SIZE + 2] = {0}; + int pageLen = NFC_PAGE_SIZE - (regAddr % NFC_PAGE_SIZE); + if (dataLen <= pageLen) + { + dataBuf[0] = (unsigned char)(regAddr >> 8) & 0xFF; + dataBuf[1] = (unsigned char)(regAddr >> 0) & 0xFF; + memcpy_s(&dataBuf[2], NFC_PAGE_SIZE, pData, dataLen); + ret = NfcI2cWrite(dataBuf, (dataLen + 2)); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cWrite fail 1, ret = %u\r\n", ret); + return FALSE; + } + return TRUE; + } + else // 跨页写 + { + dataBuf[0] = (unsigned char)(regAddr >> 8) & 0xFF; + dataBuf[1] = (unsigned char)(regAddr >> 0) & 0xFF; + memcpy_s(&dataBuf[2], NFC_PAGE_SIZE, pData, pageLen); + ret = NfcI2cWrite(dataBuf, (pageLen + 2)); //写完首页剩余长度 + if (ret != IOT_SUCCESS) + { + printf("IoTI2cWrite fail 0, ret = %u\r\n", ret); + return FALSE; + } + + dataLen -= pageLen; + regAddr += pageLen; + pData += pageLen; + for (;;) + { + if (dataLen >= NFC_PAGE_SIZE) + { + dataBuf[0] = (unsigned char)(regAddr >> 8) & 0xFF; + dataBuf[1] = (unsigned char)(regAddr >> 0) & 0xFF; + memcpy_s(&dataBuf[2], NFC_PAGE_SIZE, pData, NFC_PAGE_SIZE); + ret = NfcI2cWrite(dataBuf, (NFC_PAGE_SIZE + 2)); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cWrite fail 2, ret = %u\r\n", ret); + return FALSE; + } + + dataLen -= NFC_PAGE_SIZE; + regAddr += NFC_PAGE_SIZE; + pData += NFC_PAGE_SIZE; + } + else + { + dataBuf[0] = (unsigned char)(regAddr >> 8) & 0xFF; + dataBuf[1] = (unsigned char)(regAddr >> 0) & 0xFF; + memcpy_s(&dataBuf[2], NFC_PAGE_SIZE, pData, dataLen); + ret = NfcI2cWrite(dataBuf, dataLen + 2); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cWrite fail 3, ret = %u\r\n", ret); + return FALSE; + } + + return TRUE; + } + } + } + + return FALSE; +} + +/** + * @brief I2C读NFC EEPROM函数 + * @param addr 读取的EEPROM内存起始地址 + * @param readSize 读取的字节数 + * @param memBuf 读取的数据缓冲区 + * @return 返回TRUE表示读取数据成功 + */ +BOOL TWNfcI2CReadMem(unsigned int addr, unsigned int readSize, unsigned char *memBuf) +{ + int ret = 0; + + if (memBuf == NULL) + { + printf("TWNfcI2CReadMem() param err: memBuf = NULL\r\n"); + return FALSE; + } + + if (addr < NFC_EEPROM_ADDR_START) + { + printf("TWNfcI2CReadMem() param err: addr = %02x, NFC_EEPROM_ADDR_START = %02x\r\n", + addr, NFC_EEPROM_ADDR_START); + return FALSE; + } + + if ((addr + readSize - 1) > NFC_EEPROM_ADDR_END) + { + printf("TWNfcI2CReadMem() param err: readSize is overflow! readSize = %u, romSize = %u\r\n", + readSize, (NFC_EEPROM_ADDR_END - NFC_EEPROM_ADDR_START + 1)); + return FALSE; + } + + unsigned char dataBuf[2] = {0}; + dataBuf[0] = (unsigned char)(addr >> 8) & 0xFF; + dataBuf[1] = (unsigned char)(addr >> 0) & 0xFF; + + ret = NfcI2cWrite(dataBuf, 2); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cWrite() fail, ret = %u\r\n", ret); + return FALSE; + } + ret = NfcI2cRead(memBuf, readSize); + if (ret != IOT_SUCCESS) + { + printf("IoTI2cRead() fail, ret = %u\r\n", ret); + return FALSE; + } + + return TRUE; +} diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_i2c.h b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_i2c.h new file mode 100755 index 0000000000000000000000000000000000000000..462a1c6a8f0aa41bec37032d3f4ff5464fd43c33 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_i2c.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _TW_NFC_I2C_H +#define _TW_NFC_I2C_H +#include "tw_nfc_adapt.h" +#include "tw_nfc_ndef.h" + +/** + * @brief I2C写NFC EEPROM函数 + * @param addr 写入的EEPROM内存起始地址 + * @param mem 带写入的数据信息 + * @return 返回TRUE表示写入数据成功 + */ +BOOL TWNfcI2CWriteMem(unsigned int addr, MemFrame *mem); + +/** + * @brief I2C读NFC EEPROM函数 + * @param addr 读取的EEPROM内存起始地址 + * @param readSize 读取的字节数 + * @param memBuf 读取的数据缓冲区 + * @return 返回TRUE表示读取数据成功 + */ +BOOL TWNfcI2CReadMem(unsigned int addr, unsigned int readSize, unsigned char *memBuf); + +#endif diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_ndef.c b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_ndef.c new file mode 100755 index 0000000000000000000000000000000000000000..249bb47c07c8cbe386e35787017d696aa6dfff11 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_ndef.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tw_nfc_ndef.h" + +/** + * @brief NDEF包制作函数 + * @param ndef 传入NDEF相关参数 + * @param mem 保存根据NDEF参数制作的NDEF数据 + * @return 返回TRUE表示NDEF数据制作成功 + */ +BOOL TWNdefPackMake(NdefFrame *ndef, MemFrame *mem) +{ + if (ndef->payloadLen > NDEF_RECORD_SIZE) + { + printf("payloadLen is too long, payloadLen = %u, maxLen = %u\r\n", 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: + printf("not support packtype \r\n"); + return FALSE; + } + + mem->data[1] = 0x01; + switch (ndef->dataType) + { + case RTD_UTF8: + ndef->payloadLen += 3; + break; + + case RTD_URI: + ndef->payloadLen += 1; + break; + + default: + printf("not support dataType \r\n"); + return FALSE; + } + mem->data[2] = ndef->payloadLen; + mem->data[3] = ndef->dataType; + mem->len = ndef->payloadLen + 4; + + if (ndef->dataType == RTD_UTF8) + { + mem->data[4] = 2; + mem->data[5] = 'z'; + mem->data[6] = 'h'; + memcpy_s(&mem->data[7], ndef->payloadLen, ndef->payload, ndef->payloadLen); + } + else + { + mem->data[4] = ndef->uriVal; + memcpy_s(&mem->data[5], ndef->payloadLen, ndef->payload, ndef->payloadLen); + } + + return TRUE; +} + +/** + * @brief NDEF包解析函数 + * @param ndef 保存解析后的NDEF相关参数 + * @param mem 被解析的NDEF数据 + * @return 返回TRUE表示NDEF数据解析成功 + */ +BOOL TWNdefPackParsing(NdefFrame *ndef, unsigned char *mem) +{ + NdefHead head; + + memcpy_s(&head, 1, &mem[0], 1); + if(head.IL == 1) + { + printf("TWNdefPackParsing() err: dont support ndef ID type\r\n"); + return FALSE; + } + + if(head.SR != 1) + { + printf("TWNdefPackParsing() err: dont support ndef SR = 0 type\r\n"); + return FALSE; + } + + if(head.TNF != TNF_INSIDE_RTD) + { + printf("TWNdefPackParsing() err: ndef TNF != TNF_INSIDE_RTD type\r\n"); + return FALSE; + } + + ndef->payloadLen = mem[2]; + if(ndef->payloadLen > NDEF_RECORD_SIZE) + { + printf("TWNdefPackParsing() err: payloadLen = %u, NDEF_RECORD_SIZE = %u\r\n",ndef->payloadLen,NDEF_RECORD_SIZE); + return FALSE; + } + + ndef->dataType = mem[3]; + if((ndef->dataType != RTD_UTF8)&&(ndef->dataType != RTD_URI)) + { + printf("TWNdefPackParsing() err: dataType is invalid\r\n"); + return FALSE; + } + + 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: printf("TWNdefPackParsing() err: packtype is invalid!\r\n"); return FALSE; + } + + if(ndef->dataType == RTD_UTF8) + { + ndef->payloadLen -= 3; + memcpy_s(ndef->payload,NDEF_RECORD_SIZE,&mem[4+3], ndef->payloadLen); + } + else + { + ndef->uriVal = mem[4]; + ndef->payloadLen -= 1; + memcpy_s(ndef->payload,NDEF_RECORD_SIZE,&mem[4+1], ndef->payloadLen); + } + + return TRUE; +} diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_ndef.h b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_ndef.h new file mode 100755 index 0000000000000000000000000000000000000000..67000ad2a41afe8113cbefd88b9091eb03cfde09 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/frameworks/tw_nfc_ndef.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _TW_NFC_NDEF_H +#define _TW_NFC_NDEF_H +#include "tw_nfc_adapt.h" + +#define NFC_TLV_HEAD 0x03 +#define NDEF_RECORD_SIZE 256 + +// 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; + unsigned char payloadLen; + unsigned char payload[NDEF_RECORD_SIZE]; +} NdefFrame; + +// 普通内存数据结构体 +typedef struct{ + int len; + unsigned char data[NDEF_RECORD_SIZE + 4]; +} MemFrame; + +// NDEF格式链表,用于NDEF标签解码 +typedef struct NdefList{ + struct NdefList *next; + NdefFrame ndef; +}NdefParsingList; + +/** + * @brief NDEF包制作函数 + * @param ndef 传入NDEF相关参数 + * @param mem 保存根据NDEF参数制作的NDEF数据 + * @return 返回TRUE表示NDEF数据制作成功 + */ +BOOL TWNdefPackMake(NdefFrame *ndef, MemFrame *mem); + +/** + * @brief NDEF包解析函数 + * @param ndef 保存解析后的NDEF相关参数 + * @param mem 被解析的NDEF数据 + * @return 返回TRUE表示NDEF数据解析成功 + */ +BOOL TWNdefPackParsing(NdefFrame *ndef, unsigned char *mem); + +#endif diff --git a/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/interfaces/tw_nfc_kits.h b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/interfaces/tw_nfc_kits.h new file mode 100755 index 0000000000000000000000000000000000000000..d3761aa41fe89a8aa81926dc5c1f5b686429d276 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_nfc_lib/interfaces/tw_nfc_kits.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _TW_NFC_KITS_H +#define _TW_NFC_KITS_H +#include "tw_nfc.h" + +/** +* 特别注意: +* 此工具包暂时只支持以下ndef格式: +* 1. 单个ndef record数据payload长度最大只支持256byte(默认为256byte),可在tw_nfc_ndef.h中修改定义 +* 2. 只支持标准RTD格式中的UTF8数据格式和URI数据格式 +* 3. 不支持带ID的ndef包格式 +*/ + +/** + * @brief NFC芯片I2C接口初始化 + */ +extern void TWNfcI2cInit(void); + +/** + * @brief 写NFC标签函数 + * @param param 待写入的NFC标签信息 + * @param tagCnt 待写入的NFC标签个数 + * @return 返回TRUE表示写入NFC标签成功 + */ +extern BOOL TWNfcTagWrite(NdefFrame *param, unsigned char tagCnt); + +/** + * @brief 读NFC标签函数 + * @return 返回读取到的NFC标签链表头 + */ +extern NdefParsingList *TWNfcTagRead(void); + +/** + * @brief 读NFC标签释放函数 + * @param list 待释放的NFC标签链表头 + */ +extern void NfcReadTagFree(NdefParsingList *list); + +#endif diff --git a/applications/app/TW401_APP_wifi_nfc/tw_wifi_nfc.c b/applications/app/TW401_APP_wifi_nfc/tw_wifi_nfc.c new file mode 100755 index 0000000000000000000000000000000000000000..f0b77b5fbaefc7c0cff408af9d3298a69c5df29c --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_wifi_nfc.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "cJSON.h" +#include "cmsis_os2.h" +#include "ohos_init.h" +#include "tw_nfc_kits.h" +#include "wifi_device.h" +#include "tw_wifi_sta.h" + + +static TWWifiInfo TWReadWifiInfoFromNfcTags(void) { + TWNfcI2cInit(); + osDelay(10); + + TWWifiInfo m_wifiInfo = {0}; + + for (;;) { + + NdefParsingList *head = TWNfcTagRead(); + + unsigned char nfc_content[NDEF_RECORD_SIZE] = {0}; + + NdefParsingList *node = head->next; + if (head != NULL && node != NULL) { + memset(nfc_content, '\0', sizeof(nfc_content)); + memcpy(nfc_content, node->ndef.payload, node->ndef.payloadLen); + + printf("nfctag: %s \r\n", nfc_content); + + cJSON *cjson = cJSON_Parse(nfc_content); + if (cjson != NULL) { + cJSON *ssidItem = cJSON_GetObjectItem(cjson, "ssid"); + if (ssidItem != NULL) { + char *c_ssid = cJSON_GetStringValue(ssidItem); + memcpy(m_wifiInfo.ssid, c_ssid, strlen(c_ssid)); + } + + cJSON *pwdItem = cJSON_GetObjectItem(cjson, "pwd"); + if (pwdItem != NULL) { + char *c_password = cJSON_GetStringValue(pwdItem); + memcpy(m_wifiInfo.password, c_password, strlen(c_password)); + } + } + } + + NfcReadTagFree(head); + + if (m_wifiInfo.ssid != NULL && strlen(m_wifiInfo.ssid) > 0) { + break; + } + + osDelay(200); + } + + return m_wifiInfo; +} + +static void *TWWifiNfcThreadTask(void) { + + TWWifiInfo m_wifiInfo = TWReadWifiInfoFromNfcTags(); + + printf("wifi ssid: %s , password: %s \r\n", m_wifiInfo.ssid, m_wifiInfo.password); + + TWWifiConnect(m_wifiInfo); +} + +static void TWWifiNfcExample(void) { + printf("\nentry wifi nfc example.\r\n"); + + osThreadAttr_t attr; + + attr.name = "TWWifiNfcExample"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024 * 4; + attr.priority = 25; + + if (osThreadNew((osThreadFunc_t)TWWifiNfcThreadTask, NULL, &attr) == NULL) { + printf("Falied to create TWWifiNfcThreadTask!\n"); + } +} + +APP_FEATURE_INIT(TWWifiNfcExample); diff --git a/applications/app/TW401_APP_wifi_nfc/tw_wifi_sta.c b/applications/app/TW401_APP_wifi_nfc/tw_wifi_sta.c new file mode 100755 index 0000000000000000000000000000000000000000..5d638d4e1323beca56f2f63571529a433a66fd93 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_wifi_sta.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tw_wifi_sta.h" + +#include +#include +#include + +#include "cmsis_os2.h" +#include "lwip/api_shell.h" +#include "lwip/netifapi.h" +#include "wifi_device.h" + +int g_wifiState = 0; + +/** + * @brief 打印WifiLinkedInfo信息 + * @param info 需要打印信息的WifiLinkedInfo指针 + */ +static void PrintWifiLinkedInfo(WifiLinkedInfo *info) { + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char *mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + printf("info: bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, + info->ssid); +} + +/** + * @brief WiFi连接状态改变回调 + * @param state WiFi连接状态,参考WifiEventState + * @param info WiFi连接信息 + */ +static void OnWifiConnectionChanged(int state, WifiLinkedInfo *info) { + if (!info) return; + + printf("%s %d, state = %d \r\n", __FUNCTION__, __LINE__, state); + PrintWifiLinkedInfo(info); + + g_wifiState = state; +} + +/** + * @brief WiFi扫描状态改变回调 + * @param state WiFi连接状态,参考WifiEventState + * @param size + */ +static void OnWifiScanStateChanged(int state, int size) { + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, + size); +} + +/** + * @brief 毫秒级延时 + * @param ms 需要延迟的毫秒数 + */ +static void Delay(uint32_t ms) { + uint32_t usPerTicks = (1000 * 1000) / osKernelGetTickFreq(); + osDelay((ms * 1000) / usPerTicks); + usleep((ms * 1000) % usPerTicks); +} + +int TWIsWifiConnected(void) { + if (IsWifiActive()) { + WifiLinkedInfo wifiLinkedInfo = {0}; + WifiErrorCode wifiErrorCode = GetLinkedInfo(&wifiLinkedInfo); + if (WIFI_SUCCESS == wifiErrorCode) { + return WIFI_CONNECTED == wifiLinkedInfo.connState && + wifiLinkedInfo.ipAddress != 0; + } + } + + return 0; +} + +void TWWifiConnect(TWWifiInfo wifiInfo) { + WifiErrorCode errCode; + + WifiEvent eventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged}; + + WifiDeviceConfig apConfig = {0}; + memcpy(apConfig.ssid, wifiInfo.ssid, strlen(wifiInfo.ssid)); + memcpy(apConfig.preSharedKey, wifiInfo.password, strlen(wifiInfo.password)); + apConfig.securityType = WIFI_SEC_TYPE_PSK; + + Delay(10); + + errCode = RegisterWifiEvent(&eventListener); + printf("RegisterWifiEvent errCode: %d\r\n", errCode); + + int networkId = -1; + //启动WiFi STA模式 + errCode = EnableWifi(); + printf("EnableWifi errCode: %d\r\n", errCode); + Delay(100); + + errCode = AddDeviceConfig(&apConfig, &networkId); + printf("AddDeviceConfig errCode: %d\r\n", errCode); + + g_wifiState = 0; + errCode = ConnectTo(networkId); + printf("ConnectTo(%d) errCode: %d\r\n", networkId, errCode); + + while (!g_wifiState) { + Delay(10); + } + printf("g_wifiState: %d\r\n", g_wifiState); + Delay(3000); + + // 联网业务开始 + // 这里是网络业务代码... + struct netif *iface = netifapi_netif_find("wlan0"); + if (iface) { + err_t ret = netifapi_dhcp_start(iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + Delay(2000); // 等待DHCP服务分配IP地址 + + ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + + g_wifiState = WIFI_STATE_AVALIABLE; + + } + + printf("The Niobe connect wifi success. \r\n"); +} diff --git a/applications/app/TW401_APP_wifi_nfc/tw_wifi_sta.h b/applications/app/TW401_APP_wifi_nfc/tw_wifi_sta.h new file mode 100755 index 0000000000000000000000000000000000000000..1cdbd81cce04704dacb258dd740f08c3daab83e8 --- /dev/null +++ b/applications/app/TW401_APP_wifi_nfc/tw_wifi_sta.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Talkweb Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WIFI_STA_H +#define WIFI_STA_H + +typedef struct { + unsigned char ssid[32]; + unsigned char password[32]; +} TWWifiInfo; + + +int TWIsWifiConnected(void); + + +void TWWifiConnect(TWWifiInfo wifiInfo); + +#endif +