初出茅庐的小李博客之机智云获取网络实时时间(NTP)

news2024/9/22 8:33:55

机智云获取网络实时时间

机智云代码中其实这么一个函数gizwitsGetNTP( )可以获取网络时间,今天就在STM32F407上教大家如何通过机智云获取NTP网络时间。

简单介绍一下NTP:

网络时间同步现在有2种同步协议NTP和PTP,NTP与PTP不同在于时间戳的产生位置。NTP是通过软件来记录协议相关网络包的发出和到达时刻,同步精度可以达到优于10ms。

NTP 是网络时间协议(Network Time Protocol),他用来同步网络中各个计算机时间的协议。在机智云串口协议中,支持获取 NTP 网络同步时间的功能。

网络时间同步:

网络时间同步是指将计算机或设备的时间与网络上的时间源保持一致。

NTP网络时间同步服务器:

NTP网络时间服务器是为网络设备提供精确、标准、安全、可靠和多功能的时间服务的最佳解决方案,能提供精确的同步时钟信号

我们实现的原理就是通过编程控制Wifi模块连上机智云的网络时间服务器从而获取一个跟网络同步的时间,这个时间可以有很多用途

例如可以作为校准RTC等。

具体方式:

找到API接口函数:

在这里插入图片描述

分析API接口函数:

/**
* @brief Get the the network time

* Protocol 4.13:"Device MCU send" of "the MCU requests access to the network time"

* @param[in] none
* @return none
*/
void gizwitsGetNTP(void)
{
    int32_t ret = 0;
    protocolCommon_t getNTP;

    gizProtocolHeadInit((protocolHead_t *)&getNTP);
    getNTP.head.cmd = CMD_GET_NTP;
    getNTP.head.sn = gizwitsProtocol.sn++;
    getNTP.head.len = exchangeBytes(sizeof(protocolCommon_t)-4);
    getNTP.sum = gizProtocolSum((uint8_t *)&getNTP, sizeof(protocolCommon_t));
    ret = uartWrite((uint8_t *)&getNTP, sizeof(protocolCommon_t));
    if(ret < 0)
    {
        GIZWITS_LOG("ERR[NTP]: uart write error %d \n", ret);
    }

    gizProtocolWaitAck((uint8_t *)&getNTP, sizeof(protocolCommon_t));
}

从源码中可以看到:

第一步:定义结构体变量

protocolCommon_t getNTP;//定义了一个结构体变量

构体类型如下:


/** Protocol common data frame(4.2、4.4、4.6、4.9、4.10) protocol structure */
typedef struct
{
    protocolHead_t          head;                   ///< Protocol standard header structure
    uint8_t                 sum;                    ///< checksum
} protocolCommon_t;

这个结构体里面有两个成员:
第1个仍然是一个结构体:

/** Protocol standard header structure */
typedef struct
{
    uint8_t   head[2];       ///< The head is 0xFFFF
    uint16_t  len;  ///< From cmd to the end of the entire packet occupied by the number of bytes
    uint8_t   cmd;                    ///< command
    uint8_t   sn;                     ///< 
    uint8_t   flags[2];               ///< flag,default is 0
} protocolHead_t;

第2个则是一个校验结果sum

第二步:填充结构体信息:

填充内容包括:0xFF 0xFF 数据桢头

命令字节: cmd

sn: sn

字节数目:len

校验结果:sum


gizProtocolHeadInit((protocolHead_t *)&getNTP);
getNTP.head.cmd = CMD_GET_NTP;
getNTP.head.sn = gizwitsProtocol.sn++;
getNTP.head.len = exchangeBytes(sizeof(protocolCommon_t)-4);
getNTP.sum = gizProtocolSum((uint8_t *)&getNTP, sizeof(protocolCommon_t));
ret = uartWrite((uint8_t *)&getNTP, sizeof(protocolCommon_t));

校验采用累积和校验:

/*
* @brief Checksum calculation
* @param [in] buf   : data 
* @param [in] len   : data len
* @return sum : Checksum
*/
  uint8_t ICACHE_FLASH_ATTR gizProtocolSum(uint8_t *buf, uint32_t len)
  {
    uint8_t     sum = 0;
    uint32_t    i = 0;
    if(buf == NULL || len <= 0)
    {
        return 0;
    }
    for(i=2; i<len-1; i++)
    {
        sum += buf[i];
    }
    return sum;
  }

第三步把组包好的数据发送到Wifi模块

调用接口:

/*
* @brief uartWrite
* Serial write operation, send data to the WiFi module
* @param buf      : Data address
* @param len       : Data length
* @return : Not 0,Serial send success;
*           -1,Input Param Illegal
*/
int32_t uartWrite(uint8_t *buf, uint32_t len)
{
    uint32_t i = 0;
    if(NULL == buf)
    {
        return -1;
    }
    #ifdef PROTOCOL_DEBUG   //如果宏定义了打印的宏 则打印日志  MCU发送到wifi的信息
    GIZWITS_LOG("MCU2WiFi[%4d:%4d]: ", gizGetTimerCount(), len);
    for(i=0; i<len; i++)
    {
        GIZWITS_LOG("%02x ", buf[i]);
    }
    GIZWITS_LOG("\n");
    #endif

    for(i=0; i<len; i++)
    {
           //MCU跟WiFi通信的接口底层仍然是串口通信  这里是串口2
			USART_SendData(USART2, buf[i]);
			while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
            if(i >=2 && buf[i] == 0xFF)//除了帧头部分的0xFF原样发 后面遇到的都要在后面补上0x55 这个是协议规定
            {
                //MCU跟WiFi通信的接口底层仍然是串口通信  这里是串口2
                USART_SendData(USART2,0x55);
                while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
            }
    }
    return len;
}

第四步:根据写入的结果打印日志信息


    ret = uartWrite((uint8_t *)&getNTP, sizeof(protocolCommon_t));
    if(ret < 0)
    {
        GIZWITS_LOG("ERR[NTP]: uart write error %d \n", ret);//返回值是-1则代表出现了错误
    }

第五步:把定义的结构体部分关键信息赋值到WaitAck这个结构体中

gizProtocolWaitAck((uint8_t *)&getNTP, sizeof(protocolCommon_t));

/*
* @brief Protocol ACK check processing function
* @param [in] data            : data adress
* @param [in] len             : data length
* @return 0, suceess; other, failure
*/
  static int8_t gizProtocolWaitAck(uint8_t *gizdata, uint32_t len)
  {
    if(NULL == gizdata)
    {
        GIZWITS_LOG("ERR: data is empty \n");
        return -1;
    }
    memset((uint8_t *)&gizwitsProtocol.waitAck, 0, sizeof(protocolWaitAck_t));//
    memcpy((uint8_t *)gizwitsProtocol.waitAck.buf, gizdata, len);
    gizwitsProtocol.waitAck.dataLen = (uint16_t)len;
    gizwitsProtocol.waitAck.flag = 1;
    gizwitsProtocol.waitAck.sendTime = gizGetTimerCount();
    return 0;
  }

protocolWaitAck_t结构体成员如下


/** resend strategy structure */
typedef struct
{
    uint8_t     num;                    ///< resend times
    uint8_t     flag;                   ///< 1,Indicates that there is a need to wait for the ACK;0,Indicates that there is no need to wait for the ACK
    uint8_t      buf[MAX_PACKAGE_LEN];   ///< resend data buffer
    uint16_t     ataLen;                ///< resend data length
    uint32_t     sendTime;               ///< resend time
} protocolWaitAck_t;
                        

改结构体嵌套在gizwitsProtocol_t中
在这里插入图片描述

/** Protocol main and very important struct */
typedef struct
{
    uint8_t issuedFlag;                             ///< P0 action type
    uint8_t protocolBuf[MAX_PACKAGE_LEN];           ///< Protocol data handle buffer
    uint8_t transparentBuff[MAX_PACKAGE_LEN];       ///< Transparent data storage area
    uint32_t transparentLen;                        ///< Transmission data length
    
    uint32_t sn;                                    ///< Message SN
    uint32_t timerMsCount;                          ///< Timer Count 
    
    protocolWaitAck_t waitAck;                      ///< Protocol wait ACK data structure
    
    eventInfo_t issuedProcessEvent;                 ///< Control events
    eventInfo_t wifiStatusEvent;                    ///< WIFI Status events
    eventInfo_t NTPEvent;                           ///< NTP events
    eventInfo_t moduleInfoEvent;                    ///< Module Info events

	gizwitsReport_t reportData;                     ///< The protocol reports data for standard product
    dataPoint_t gizCurrentDataPoint;                ///< Current device datapoints status
    dataPoint_t gizLastDataPoint;                   ///< Last device datapoints status
    moduleStatusInfo_t wifiStatusData;              ///< WIFI signal intensity
    protocolTime_t TimeNTP;                         ///< Network time information
#if MODULE_TYPE
    gprsInfo_t   gprsInfoNews;
#else  
    moduleInfo_t  wifiModuleNews;                   ///< WIFI module Info
#endif
	
}gizwitsProtocol_t; 

至此代码的分析完毕,我们只需要大概的流程即可,里面实现的细节暂且不用深究,接下来我们来写一个代码调用该API并把获取到的网络实时时间通过串口调试工具进行打印查看。

编写应用代码方式:

既然是获取网络时间我们就需要等到入网成功之后才可以获取因为只有这样获取到的时间才是准确的也只有这样我们才能获取到准确的时间。

查找连上WIFI的判断我们定义一个全部变量来表示联网成功!

首先在 main.c文件中,定义一个 wifi_sta 变量,用来记录 wifi 连接状态,当模组连上机智云的服务器时,会返回WIFI_CON_M2M 的事件,断开时返回WIFI_DISCON_M2M,所以我们就在这两个地方添加标志位并且要引入外部变量,否则会报错,如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nZo3s2e-1688801965975)(C:\Users\23206\AppData\Roaming\Typora\typora-user-images\image-20230708145640728.png)]
在这里插入图片描述

部分代码如下:

    case WIFI_CON_M2M:
            wifi_sta = 1;//连上网络修改标志位为1
            GIZWITS_LOG("wifi_sta = 1\n");
            break;
        case WIFI_DISCON_M2M:
            wifi_sta = 0;//断开网络修改标志位为0
            GIZWITS_LOG("wifi_sta = 0\n");
            break;
        case WIFI_RSSI:
            GIZWITS_LOG("RSSI %d\n", wifiData->rssi);
            break;
        case TRANSPARENT_DATA:
            GIZWITS_LOG("TRANSPARENT_DATA \n");
            //user handle , Fetch data from [data] , size is [len]
            break;
        case WIFI_NTP:
            GIZWITS_LOG("WIFI_NTP : [%d-%d-%d %02d:%02d:%02d][%d] \n",ptime->year,ptime->month,ptime->day,ptime->hour,ptime->minute,ptime->second,ptime->ntp);
            break;
        case MODULE_INFO:
            GIZWITS_LOG("MODULE INFO ...\n");

获取时间的代码实现:

打印代码:

在这里插入图片描述

获取代码:


void userHandle(void)
{
	static uint32_t count_time = 0;
	count_time++;
	delay_nms(100);
	if(count_time %10==0)
	{
		if(wifi_sta==1)
		{
				gizwitsGetNTP();//每1秒调用一次网络时间 前提是连上网络之后	
		}
		else if(wifi_sta ==0)
		{
			printf("未连接到网络...\r\n");
		}
	}
	currentDataPoint.valuebeep = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_0);
	currentDataPoint.valueyzh  = GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_4);
}

实现结果:

在这里插入图片描述

网络时间就是当前时间:2023年7月8日15点31分08秒 这个时间如果用于更新RTC实现并且实现掉电存储就十分准确了

至此:机智云网络获取时间已经完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/733014.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kubernetes对象深入学习之二:细说schema.ObjectKind

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 在前文咱们对对象体系有了大概了解&#xff0c;接下来就要按照前面换分的三个知识区域逐个深入学习&#xff0c;今天从最简单的对象类型开始 runtime.Object…

PWM 输出实验(stm32)

目录 PWM的代码pwm.cpwm.h main.c 说明&#xff1a;以下内容参考正点原子的资料 PWM的代码 pwm.c //TIM3 PWM部分初始化 //PWM输出初始化 //arr&#xff1a;自动重装值 //psc&#xff1a;时钟预分频数 void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitSt…

华为云CodeArts Build-云端化的编译构建平台

随着互联网企业业务种类增多&#xff0c;业务跨平台&#xff0c;多语言编程成为常态。 传统应用软件为本地应用&#xff0c;业务复杂&#xff0c;软件规模大&#xff0c;编译构建耗时长&#xff0c;而且移动终端APP业务变化快&#xff0c;交付要求短平快。 因此一个支持多语言…

环型链表oj

文章目录 题目描述解决方法 题目描述 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中…

java 阿里云直播配置及推拉流地址获取

一、开通阿里云直播 首先进入阿里云直播产品主页&#xff1a;https://www.aliyun.com/product/live 。 点击下方的“立即开通”。 如果是还未注册的用户请按照页面提示进行完成注册并实名认证。 2、首次进入会提示开通服务&#xff0c;点击“开通服务”&#xff0c;然后选择计…

[C++] 万字 - C++异常处理分析介绍: 异常概念、异常抛出与捕获匹配原则、重新抛出、异常安全、异常体系...

C语言 错误处理方式 在C语言中, 代码发生错误一般会有两种处理方式: 终止程序. 比如 直接使用assert()断言. 或者直接崩溃 返回、设置错误码 C语言某些函数执行失败, 但是结果不足以导致致命问题时, 就会将错误码设置在errno中. 用户可以通过strerr(errno)来获取错误信息. …

Linux的管道符详解

&#xff08;该图由AI绘制 关注我 学习AI画图&#xff09; 目录 管道&#xff08;重点&#xff09; 1、管道符 2、过滤&#xff08;筛选&#xff09;功能 3、特殊功能&#xff08;了解&#xff09; 4、统计功能&#xff08;重点&#xff09; 5、xargs命令扩展 管道&…

多元分类预测 | Matlab全连接神经网络(DNN)分类预测,多特征输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 全连接神经网络(DNN)分类预测,多特征输入模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可出分类效果图,迭代优化图,混淆矩阵图。 部分源码

设计数据库时,字段“是否可用”该取什么英文名?研究active/enable/state/progress的区别

一条记录发布后&#xff0c;除了删除状态&#xff0c;还存在可用、不可用状态&#xff08;并非审核状态&#xff09;&#xff0c;那么这个字段在数据库中该取什么名字呢&#xff1f;先告诉结果&#xff1a;使用active英文单词衍生出的is_active。 表可用 active - 意为活跃或生…

Java经典面试题下包含答案

21.String、StringBuffer和StringBuilder的区别是什么&#xff1f; 线程安全&#xff1a; String中的对象是不可变的&#xff0c;线程安全StringBuffer对方法加了同步锁&#xff0c;所以是线程安全的StringBuilder没有对方法加同步锁&#xff0c;所以是非线程安全的 使用效率…

【STM32单片机】STM32控制SG90舵机的PWM部分参数的设置解答

STM32控制SG90舵机的PWM部分参数的设置解答 一、舵机控制要知道的知识二、PWM的参数要怎么计算1、为什么要分频呢&#xff1f;2、为什么选择TIM_OCMode_PWM1呢&#xff1f; 每天进步一点点 笔记仅供自学&#xff0c;用来回看复习&#xff0c;不一定适合你&#xff0c;如有错误请…

论青春线上书屋的设计与实现(论文+源码)_kaic

目 录 摘 要 III 第一章 绪论 1 1.1本课题研究背景与意义 1 1.2本课题国内外研究现状 1 第二章 开发技术介绍 3 2.1JDK的安装与配置 3 2.2HTML技术 3 2.3MySQL数据库管理系统 4 2.4JDBC的使用 4 第三章 系统分析 5 3.1系统的设计要求 5 3.2系…

交通 | 动态设施选址问题

论文解读 陈迎新&#xff0c;柯斯琪&#xff0c;曲晨辉&#xff0c;张景琪 编者按 本次解读的文章是Transportation Science 2017年的 《在日益增长的市场中&#xff0c;动态设施选址问题的连续逼近方法》&#xff08;Wang, X., Lim, M. K., & Ouyang, Y. (2017). A conti…

空元素不占用位置处理

一. 问题场景&#xff1a; 如果将一个元素的CSS设置为margin-right: 10px&#xff0c;即使这个元素为空&#xff0c;那么这10px依然存在&#xff0c;效果如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&q…

【编译原理】词法分析程序设计(C语言)

目录 一、实验内容二、实验原理三、结果分析四、源代码一、实验内容 给定下表所示的一个简单语言的词法规则描述完成以下任务: (1)画出识别该语言词法规则的状态转换图; (2)依据状态转换图,设计并编制词法分析程序,实现从输入源程序中,识别出各类单词,即关键字、标识…

打工人如何利用自动化实现职场突围

作为优秀的打工人&#xff0c;如果可以将办公中的重复性、繁琐性、低效性工作自动化&#xff0c;那么将省去许多日常工作。许亚宁就是这样一个优秀的打工人&#xff0c;善于使用各类自动化工具来提升工作效率&#xff0c;上周的直播他分享了如何利用自动化工具&#xff0c;实现…

设计原则-依赖倒置原则

如同人体结构一样&#xff0c;项目代码也是需要有结构的&#xff0c;如原子逻辑块(不可再分代码块)、方法、类、模块等。结构要么是由成熟的框架搭建起来&#xff0c;要么自己手动划分&#xff0c;但是都需要保证下层模块的变动时不会影响上层模块。注意&#xff1a;这里所说的…

missing-semester————2

文章目录 shell 脚本赋值语法函数逻辑运算符命令替换进程替换通配 shell工具查看命令如何使用查找文件查找代码查找shell指令 shell 脚本 很多情况下需要执行一系列的操作并使用条件或循环这样的控制流。 大多数shell都有自己的一套脚本语言&#xff0c;包括变量、控制流和自…

006-Logstash、FileBeat、ELK整合详解

目录 ELK架构背景需求架构logstash核心概念配置文件结构插件Codec Plugin-Multiline输出&#xff1a;elasticsearch输入&#xff1a;jdbcGrok插件Grok语法 mutate插件Date插件 Logstash Queue Beats配置步骤 ELK整合步骤1&#xff1a;日志采集步骤2&#xff1a;配置Logstash接收…

ChatGLM2体验+ubuntu18.04LTS+CPU版本

ChatGPT在自然语言处理领域的表现让人振奋&#xff0c;开启了大模型在通用人工智能领域的大门。 许多工作随之跟进&#xff0c;并开源&#xff0c;凭借相对小的参数量达到近似GPT的效果&#xff0c;包括LLama&#xff0c;alpace等。 其中LLama训练语料主要选择英语&#xff0…