Linux C 用GPS时间更新系统时间的方法。

思路:

  1、GPS模块会自动收到带时间信息的消息。

    GPS模块会收到很多的协议消息带时间信息的。我们选择"$GPRMC"这条协议。其中的时间格式有的是hhmmss(时分秒)

有的是的精确到秒后两位hmmss.ss(时分秒),有的是的精确到秒后三位hmmss.ss(时分秒),具体估计需要看实际模块输出。

       2、从消息中解析出GPS收到的时间

       3、如系统时间和GPS时间差异大时,用GPS时间更新系统时间

 

GPS协议介绍:

GPS遵循一下NMEA 0183 协议

NMEA 0183 协议
NMEA 0183 是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式。目前业已成了 GPS 导航设备统一的 RTCM(Radio Technical Commission for Maritime services)标准协议。NMEA0183 协议采用 ASCII 码来传递 GPS 定位信息,我们称之为帧。帧格式形如:

$aaccc,ddd,ddd,„,ddd*hh(CR)(LF)

1. “$”:帧命令起始位

2. “aaccc”:地址域,前两位为识别符(aa),后三位为语句名(ccc)

3. “ddd,ddd”:数据内容

4. “*”:校验和前缀(也可以作为语句数据结束的标志)

5. “hh”:校验和(check sum),$与*之间所有字符 ASCII 码的校验和(各字 节做异或运算,得到校验和后,再转换 16 进制格式的 ASCII 字符)

6. “(CR)(LF)”:帧结束,回车和换行符

主要命令:

序号 命令 说明 最大帧长(Byte)

1 $GPRMC 推荐定位信息 70

2 $GPGGA GPS 定位信息 72

3 $GPVTG 地面速度信息 34

4 $RHXZ 地磁信息 24

5 $GPGSA 当前卫星信息 65

6 $GPGSV 可见卫星数 210

7 $GPGLL 大地坐标信息

指令解析:

1.$GPRMC(推荐定位信息,Recommended Minimum Specific GPS/Transit Data) $GPRMC 语句的基本格式如下: $GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR)(LF)

(1)UTC 时间,hhmmss(时分秒)

(2)定位状态,A=有效定位,V=无效定位

(3)纬度 ddmm.mmmmm 度分)

(4)纬度半球 N(北半球)或 S(南半球)

(5)经度 dddmm.mmmmm 度分)

(6)经度半球 E(东经)或 W(西经)

(7)地面速率(000.0~999.9 节)

(8)地面航向(000.0~359.9 度,以真北方为参考基准)

(9)UTC 日期,ddmmyy(日月年)

(10)磁偏角(000.0~180.0 度,前导位数不足则补 0)

(11)磁偏角方向,E(东)或 W(西) (12)模式指示(A=自主定位,D=差分,R=RTK,E=估算,N=数据无效) 举例如下: $GPRMC,084103.00,A,2233.395441,N,11356.556656,E,0.035,,220618,,,A*7A

 

2.$GPGGA(GPS 定位信息,Global Positioning System Fix Data) $GPGGA 语句的基本格式如下(其中 M 指单位 M,下同): $GPGGA,(1),(2),(3),(4),(5),(6),(7),(8),(9),M,(10),M,(11),(12)*hh(CR)( LF)

(1)UTC 时间,格式为 hhmmss.ss;

(2)纬度,格式为 ddmm.mmmmmm 度分格式);

(3)纬度半球,N 或 S(北纬或南纬);

(4)经度,格式为 dddmm.mmmmmm 度分格式);

(5)经度半球,E 或 W(东经或西经);

(6)GPS 状态,0=未定位,1=非差分定位,2=差分定位;

(7)正在使用的用于定位的卫星数量(00~12)

(8)HDOP 水平精确度因子(0.5~99.9)

(9)海拔高度(-9999.9 到 9999.9 米)

(10)大地水准面高度(-9999.9 到 9999.9 米)

(11)差分时间(从最近一次接收到差分信号开始的秒数,非差分定位,此项为 空)

(12)差分参考基站标号(0000 到 1023,首位 0 也将传送,非差分定位,此项为 空) 举例如下: $GPGGA,070343.90,2236.360900,N,11352.021690,E,1,04,68.82,-72.83,M,- 1.00,M,,*68

3.$GPVTG(地面速度信息,Track Made Good and Ground Speed) $GPVTG 语句的基本格式如下: $GPVTG,(1),T,(2),M,(3),N,(4),K,(5)*hh(CR)(LF)

(1)以真北为参考基准的地面航向(000~359 度,前面的 0 也将被传输)

(2)以磁北为参考基准的地面航向(000~359 度,前面的 0 也将被传输)

(3)地面速率(000.0~999.9 节,前面的 0 也将被传输)

(4)地面速率(0000.0~1851.8 公里/小时,前面的 0 也将被传输)

(5)模式指示(A=自主定位,D=差分,E=估算,N=数据无效) 举例如下: $GPVTG,,T,,M,0.106,N,0.196,K,A*2A

 

4.$RHXZ(地磁传感器信息) $RHXZ 语句的基本格式如下: $RHXZ,(1),(2),(3) *hh(CR)(LF)

(1)地磁传感器 X 轴的 16 进制值(高位在前,如 0057 表示 0x0057,范围 0000~FFFF,前面的 0 也将被传输)

(2)地磁传感器 Y 轴的 16 进制值(高位在前,如 FE6E 表示 0xFE6E,范围 0000~FFFF,前面的 0 也将被传输)

(3)地磁传感器 Z 轴的 16 进制值(高位在前,如 0210 表示 0x0210,范围 0000~FFFF,前面的 0 也将被传输) 举例如下: $RHXZ,0057,FE6E,0210*45

 

5.$GPGSA(当前卫星信息) $GPGSA 语句的基本格式如下: $GPGSA,(1),(2),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(4),(5 ),(6)*hh(CR)(LF)

(1)模式,M = 手动,A = 自动。

(2)定位类型,1=未定位,2=2D 定位,3=3D 定位。

(3)正在用于定位的卫星号(01~32)

(4)PDOP 综合位置精度因子(0.5-99.9)

(5)HDOP 水平精度因子 1(0.5-99.9)

(6)VDOP 垂直精度因子(0.5-99.9) 举例如下: $GPGSA,A,3,26,02,05,29,15,21,,,,,,,2.45,1.49,1.94*0E

 

6.$GPGSV(可见卫星数,GPS Satellites in View) $GPGSV 语句的基本格式如下: $GPGSV,(1),(2),(3),(4),(5),(6),(7),...,(4),(5),(6),(7)*hh(CR)(LF)

(1)GSV 语句总数。

(2)本句 GSV 的编号。

(3)可见卫星的总数(00~12,前面的 0 也将被传输)。

(4)卫星编号(01~32,前面的 0 也将被传输)。

(5)卫星仰角(00~90 度,前面的 0 也将被传输)。

(6)卫星方位角(000~359 度,前面的 0 也将被传输)

(7)信噪比(00~99dB,没有跟踪到卫星时为空)。

注:每条 GSV 语句最多包括四颗卫星的信息,其他卫星的信息将在下一条 $GPGSV 语句中输出。

举例如下: $GPGSV,3,1,12,02,39,117,25,04,02,127,,05,40,036,24,08,10,052,*7E $GPGSV,3,2,12,09,35,133,,10,01,073,,15,72,240,22,18,05,274,*7B $GPGSV,3,3,12,21,10,316,31,24,16,176,,26,65,035,42,29,46,277,18*7A

 

7.$GPGLL(定位地理信息,Geographic Position) $GPGLL 语句的基本格式如下: $GPGLL,(1),(2),(3),(4),(5),(6),(7)*hh(CR)(LF)

(1)纬度 ddmm.mmmmm(度分)

(2)纬度半球 N(北半球)或 S(南半球)

(3)经度 dddmm.mmmmm(度分)

(4)经度半球 E(东经)或 W(西经)

(5)UTC 时间:hhmmss(时分秒

(6)定位状态,A=有效定位,V=无效定位

(7)模式指示(A=自主定位,D=差分,E=估算,N=数据无效)

 

代码:

 因项目后续调整,代码写完,一直没有实际调试。参考时,请知悉。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include "uart_oper.h"
#include "gps_oper.h"
#include "play.h"

#define GPS_DEV_NAME  "/dev/ttyS0"  /*需根据实际端口修改*/
#define GPS_LEN 1024
#define TIME_VAL (10*1000)


static int gps_analyse(char * buff, GPRMC *gps_data);
static int print_gps(GPRMC * gps_data);
static void set_ensync_deal(SyncStateEnum sync_val);
static int update_time_fromgps(GPRMC * gps_data);

/**
*@brief  解析收到的gps信息
*@param  buff:收到的gps信息. 
         gps_data:返回解析到的结构体
*@return 失败返回-1;成功返回0;
*/
static int gps_analyse(char * buff, GPRMC *gps_data)
{
    char *ptr = NULL;
    if(gps_data == NULL)
    {
        return - 1;
    }    
    if(strlen(buff) < 0)
    {
        return - 1;
    }
    
    ptr = strstr(buff, "$GPRMC"); /*找到GPRMC的位置*/
    if(ptr == NULL)
    {
        return - 1;
    }
    
    sscanf(ptr, "$GPRMC,%d.%d,%c,%f,N,%f,E,%f,%f,%d,,,%c*",
        &(gps_data->time), &(gps_data->ptime), &(gps_data->pos_state),
        &(gps_data->latitude), &(gps_data->longitude), &(gps_data->speed),
        &(gps_data->direction), &(gps_data->date), &(gps_data->mode));
    
    return 0;
}
/**
*@brief  打印解析后的gps信息
*@param  gps_data:解析到的结构体
*@return 失败返回-1;成功返回0;
*/
static int print_gps(GPRMC * gps_data)
{
    if(gps_data == NULL)
    {
        return - 1;
    }
    printf("GPS state bit : %c [A:有效状态] V:无效状态]\n", gps_data->pos_state);    
    printf("GPS mode bit :%c [A:自主定位 D:查分定位]\n", gps_data->mode);
    printf("Data: 20%02d-%02d-%02d \n", (gps_data->date % 100),    /*GPRMC的日期格式为:ddmmyy*/
        ((gps_data->date % 1000) / 100), (gps_data->date / 10000));    
                                                                                
    printf("Time: %02d:%02d%02d.%03d\n", ((gps_data->time / 10000 + 8) % 24),
        ((gps_data->time % 10000) / 100), (gps_data->time % 100), gps_data->ptime);

    printf("纬度:%d度%d分%d秒\n", (int)(gps_data->latitude / 100), (int)(gps_data->latitude - ((int)(gps_data->latitude / 100 * 100))),
        (int)(((gps_data->latitude - ((int)gps_data->latitude / 100 * 100)) - ((int)gps_data->latitude - ((int)gps_data->latitude / 100 * 100))) * 60.0));
    printf("经度 :%d度%d分%d秒 \n", ((int)gps_data->longitude) / 100, (int)(gps_data->longitude - ((int)gps_data->longitude / 100 * 100)),
     (int)(((gps_data->longitude - ((int)gps_data->longitude / 100 * 100)) - ((int)gps_data->longitude - ((int)gps_data->longitude / 100 * 100)))* 60.0));

    printf("速度:%.3f m/s \n", gps_data->speed);
    return 0;
}

/*
*@brief  用gps时间更新系统时间.相差10ms时进行更新时间
*@param  none. 
*@return 不更新返回-1,更新返回0.
*/
static int update_time_fromgps(GPRMC * gps_data)
{
    struct timeval cur_tv;
    struct timeval gps_tv;
    struct tm gps_tm;
    int ret = -1;

     gps_tm.tm_year = (gps_data->date % 100) + 2000 - 1900;    /**/                
     gps_tm.tm_mon = (gps_data->date % 1000) / 100 - 1;        /**/
     gps_tm.tm_mday = (gps_data->date / 10000);                /**/
     gps_tm.tm_hour = gps_data->time / 10000;        /**/
     gps_tm.tm_min = (gps_data->time % 10000) / 100;/**/
     gps_tm.tm_sec = gps_data->time % 100;            /**/
     gps_tm.tm_isdst = - 1;
    
     gps_tv.tv_sec = mktime(&gps_tm); /*tm 转换为秒*/
     gps_tv.tv_usec = gps_data->ptime *1000;
     gettimeofday(&cur_tv, NULL);

    if(gps_tv.tv_sec != cur_tv.tv_sec)
    {
        settimeofday(&gps_tv, NULL);
        tim->set_timzone(0);
        system("hwclock -w");/*软件时间更新硬件时间*/
        tim->set_timzone(8);
        ret = 0;
    }    
    else if(((gps_tv.tv_usec - cur_tv.tv_usec) > TIME_VAL) || ((cur_tv.tv_usec - gps_tv.tv_usec) > TIME_VAL))    
    {
      /*相差10ms*/
        settimeofday(&gps_tv, NULL);
        tim->set_timzone(0);
        system("hwclock -w");/*软件时间更新硬件时间*/
        tim->set_timzone(8);
        ret = 0;
    }
    return ret;
}
/*
*@brief  set sync 枚举值(设置系统同步标识)
*@param  sync_val 设置的枚举值
*@return none.
*/
static void set_ensync_deal(SyncStateEnum sync_val)
{
    if(SetInfo.euSync != sync_val)
    {
        pthread_rwlock_wrlock(&rwlock_sys);
        SetInfo.euSync = sync_val;
        pthread_rwlock_wrlock(&rwlock_sys);
    }
}
/*
*@brief  Gps 处理线程函数
*@param  none. 
*@return none.
*/
void * Gps_proc_thread(void *arg)
{
    int fd;
    int ret;
    int n = 0;
    GPRMC gprmc;
    char buff[GPS_LEN];
    fd_set Rdfet;
    struct timeval timeout;
    struct timeval vaild_tv;
    struct timeval invaild_tv;

    pthread_detach(pthread_self());

    fd = open(GPS_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd < 0)
    {
        perror("Can't open gps uart port");
        set_ensync_deal(SYNC_STATE_NO);
        return(void *)"gps dev error";
    }
    ret = set_serial(fd, 9600, 8, 'N', 1); /*可能需要根据情况调整*/
    {
        printf("set_serial error\n");
        goto endline;    
    }

    FD_ZERO(&Rdfet);
    printf("Gps proc thread start......\n");

    for(;;)   /*循环读取gps信息*/
    {
    
        timeout.tv_sec = 3;
        timeout.tv_usec = 0;
        FD_SET(fd, &Rdfet);
        ret = select(fd + 1, &Rdfet, NULL, NULL, &timeout); /*监控fd*/
        if(ret < 0) /*出错*/
        {
            perror("select error");
            msleep(50);
        }
        else if(ret > 0) /*有数据可读*/
        {
            if((n = read(fd, buff, sizeof(buff))) < 0)    
            {
                perror("gps read error");
            }
            memset(&gprmc, 0 , sizeof(gprmc));
            gps_analyse(buff, &gprmc);
            #if DEBUG_SWITCH
            printf("buff = %s\n", buff);
            print_gps(&gprmc);
            #endif    
            if(gprmc.pos_state == 'A') /*有效*/
            {
                gettimeofday(&vaild_tv, NULL);
            //    set_ensync_deal(SYNC_STATE_OK);
                /*时间相差10ms时,更新系统时间*/
                update_time_fromgps(&gprmc);
            }
            else /*无有效数据*/
            {
                gettimeofday(&invaild_tv, NULL);
                if((invaild_tv.tv_sec - vaild_tv.tv_sec) > 3) /*距离有效GPS时间过去3秒,判断GPS无信号*/
                {
                    set_ensync_deal(SYNC_STATE_NO);
                }
            }    
        }
        else if(ret == 0)  /*timeout*/
        {
            set_ensync_deal(SYNC_STATE_NO);
        }
    } /*end for(;;) */

endline:
    set_ensync_deal(SYNC_STATE_NO);
    close(fd);
    return NULL;
}

 

本文转载于网络 如有侵权请联系删除

相关文章

  • 手把手教你 Socket 通信(TCP/IP)

    网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。下载eclipse:https://www.eclipse.org/本文将给出完整Socket通信代码,在eclipse中亲测有效。在AndroidStudio中用Java开发也是一样的,只是把代码和控件搭配一下,注册监听就好。区别就是在AS中import的声明不太一样,然后窗口不需要自己建立。效果如图在eclipse中,File→New→JavaProject→起个英文名字→Finish(我起的名字是TCP)目录结构:新建完以后有个src默认包,右键src→New→Package→输入com.net(因为程序里我用的包的名字是这个,你可以同时两个一起改)→Finish然后右键com.net→New→Class→输入T

  • 分享 Python 常见面试题及答案(上)

    之前分享了一篇很全的Java的面试题 分享Java常见面试题及答案(上) 分享Java常见面试题及答案(下) Java面试题刚发完,后台又有很多Python程序员问,要不要分享一份Python面试题,所以今天刚好分享这份Python面试题,大部分题目属于巩固基础的Python的题目,希望对你有帮助! 1、一行代码实现1--100之和利用sum()函数求和2、如何在一个函数内部修改全局变量利用global修改全局变量3、列出5个python标准库os:提供了不少与操作系统相关联的函数 sys:通常用于命令行参数re:正则匹配math:数学运算datetime:处理日期时间4、字典如何删除键和合并两个字典del和update方法 5、谈下python的GILGIL是python的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行python程序的时候会霸占python解释器(加了一把锁即GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。

  • 开发:随笔记录之 Json字符串 与 List、HashMap对象的转换

    importjava.util.ArrayList; importjava.util.HashMap; importjava.util.List; importjava.util.Map; importjava.util.Map.Entry; importnet.sf.json.JSONArray; importnet.sf.json.JSONObject; importnet.sf.json.JsonConfig; importnet.sf.json.util.JSONUtils; publicclassJsonParser{ /** *json字符串转成map * *@paramjsonStr *@return *@throwsException */ publicstaticHashMap<String,JsonValue>parse(StringjsonStr){ if(jsonStr==null||"".equals(jsonStr)){returnnull;} HashMap<String,JsonValue>retMap

  • 分享按钮栏实现小例子

    实现普通按钮+底部线条组合成的按钮。实现  使用QPushButton(按钮)和QLabel(底部线条)组合实现。底部线条实现:classLine:publicQLabel{ Q_OBJECT public: Line(QWidget*parent=NULL):QLabel(parent){} /*绘图事件*/ voidpaintEvent(QPaintEvent*) { QPainterpainter(this); /*设置画笔*/ painter.setPen(QPen(Qt::black,height())); /*画线*/ painter.drawLine(0,0,width(),0); } }; 复制按钮实现:classButton:publicQPushButton{ Q_OBJECT public: Button(constQString&text,QWidget*parent=NULL): QPushButton(text,parent) { m_line=newLine(this); m_line->setVisible(false); QString

  • 人工智能和物联网如何改善癌症治疗

    虽然人工智能和物联网可能是分开开发的,但它们的联合力量可以使癌症患者和医生能够做出更好的数据驱动决策。物联网(IoT)可以使我们的生活更轻松。医疗保健是物联网可能影响积极变化的行业之一。关于物联网如何帮助提高医疗保健效率的话题广为流传。它可以减少急诊室的等待时间,并跟踪患者和库存数据。人们也希望有一天人工智能(AI)可以帮助医生进行癌症的研究,检测和护理。AI和IoT共同可以改善癌症治疗。诊断和治疗的机会随着机器和设备之间能够更好地相互通信,诸如IBMWatson之类的AI技术以及机器人外科医师正在帮助医生从诊断到护理癌症的治疗。但是,目前,人工智能和物联网在癌症治疗领域尚无法协同工作。通常,医生越早识别症状,他们越能迅速诊断并开始治疗。各种各样的早期癌症症状都是模糊不清的,无法识别,因此可以理解,最初可能无法诊断出癌症。关键在于:人工智能和物联网可以改善癌症治疗,但它们应该协同工作。与AI平台协同工作的IoT系统将能够破译癌症风险标记并对其采取行动。他们可以在不太严重的情况下以及在更加模糊的诊断环境中这样做。这种先进的技术融合对于罕见疾病和后期预期寿命较差的疾病特别有用。对于间皮瘤这

  • java设计模式-装饰者模式

    模式定义动态的将新功能附加到对象上,在对象功能扩展方面,它比继承更有弹性。设计原则多用组合,少用继承类应设计的对扩展开放,对修改关闭。UML类图装饰者模式实例先写一个被装饰者食物的类被装饰者-食物类/** *被装饰者-食物类 */ publicclassFood{ privateStringfoodName; publicFood(){ } publicFood(StringfoodName){ this.foodName=foodName; } publicStringmake(){ returnfoodName; } }复制再定义几个装饰者类装饰者-面包类/** *装饰者-面包类 */ publicclassBreadextendsFood{ privateFoodfood; publicBread(Foodfood){ this.food=food; } publicStringmake(){ returnfood.make()+"+面包"; } }复制装饰者-奶油类/** *装饰者-奶油类 */ publicclassCreamextendsFood{

  • 交互式使用 R题(shell)

    交互式使用R交互式shell是一种很方便的环境,可以进行各种尝试,随时调整过程。与Python、Ruby等语言一样,R也提供了shell环境。本文开始的例子就是以交互的方式使用R。当打开R控制台时,R会显示命令提示符”>”,此时可以输入命令。下面是交互式使用R的几个例子:例一:help.start()#启动在线帮助,会打开浏览器。 x<-rnorm(50);y<-rnorm(x)#产生两个随机向量x和y plot(x,y)#使用x,y画二维散点图,会打开一个图形窗口 ls()#查看当前工作空间里面的R对象 rm(x,y)#清除x,y对象 x<-1:20#相当于x=(1,2,…,20)复制例二:x<-1:20#等价于x=(1,2,...,20)。 w<-1+sqrt(x)/2#标准差的`权重'向量。 dummy<-data.frame(x=x,y=x+rnorm(x)*w)#创建一个由x和y构成的双列数据框 dummy#查看dummy对象中的数据。 fm<-lm(y~x,data=dummy)#拟合y对x的简单线性回归 summa

  • 跟我一起学mybatis框架Ⅰ

    ?个人主页:楠慧 ?简介:一个大二的科班出身的,主要研究Java后端开发 ⏰座右铭:成功之前我们要做应该做的事情,成功之后才能做我们喜欢的事 ?过客的你,可以给博主留下一个小小的关注吗?这是给博主最大的支持。以后博主会更新大量的优质的作品!!!!一.Mybatis快速入门1.1框架介绍框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求! 如图: 1.2ORM介绍ORM(ObjectRelationalMapping):对象关系映射 指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术。 如图: 具体映射关系如下图:1.3原始jdbc操作(查询数据)1.4原始jdbc操作(插入数据)1.5原始jdbc操作的分析原始JDBC的操作问题分析​1.频繁创建和销毁数据库的连接会造成系统资源浪费从而影响系统性能。2.sql语句在代码中硬编码,如果要修改sql语句,就需要修改java代码,造成代码不易维护。 3.查询操作时,需要手动将结果集中的数据封装到实体对象中。 4.增删改查操作需要参数时,需要手动将实体对象的数据设置到sq

  • 项目工期延后有哪些补救措施?

    大部分项目经理都面临过项目延期的情况,特别是在软件开发领域,项目延期情况尤为严重。项目管理者的真正挑战,不是发现问题和记录问题,而是预见问题、控制问题和解决问题。 因此当项目出现了延期状况时,我们需要思考有效的”拯救“之策,尽最大可能将未被终止的项目进行调整以期拉回进度。接下来,就说说,项目成员们如何做,才能将延误的时间”抢“回来,让项目可以重新正常呢?   一、项目延期之后的补救措施   项目延期补救措施一:项目的计划变更 当我们发现项目进度已经偏离,而且已经到了不可纠正的地步,那么我们可以去走变更流程。 由于项目基准发生变化,项目的目标也会被改变,这意味着我们可以重新实现项目目标,所以项目计划变更是一种补救措施。往往当我们使用这种补救措施的时候,意味着项目的进度延期已经不可能被纠正了,所以我们要调整项目的基准,改变项目的目标。 不过我们并不推崇项目计划变更这样的补救方式。因为从项目成功的角度来说,我们在更希望的是,能够实现项目最初的目标,而不是一有延期就去改变项目目标。如果每次延期项目经理都去改变项目目标,最后绩效还很好的话,那受损失的其实是公司。  

  • httprunner的env里,有空格和注释报错问题解决

    .env testenv=xxxxx 1.当文件内包含注释或空行时,抛出异常httprunner.exceptions.FileFormatError:.envformaterror 原因是源代码中没有对空行和#号做处理,代码片段(loader-130): withopen(dot_env_path,mode="rb")asfp: forlineinfp: #maxsplit=1 ifb"="inline: variable,value=line.split(b"=",1) elifb":"inline: variable,value=line.split(b":",1) else: raiseexceptions.FileFormatError(".envformaterror") 复制 2.加上判断忽略掉注释和空行,就不会报错了(源代码路径:httprunner-->loader.py) withopen(dot_env_path,mode="rb")asfp: forlineinfp: #maxsplit=1 line=line.strip() ifnotlen(line)

  • [leetcode]53. 最大子序和*

    53.最大子序和 Difficulty:简单 给定一个整数数组nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入:[-2,1,-3,4,-1,2,1,-5,4], 输出:6 解释: 连续子数组 [4,-1,2,1]的和最大,为 6。 复制 进阶: 如果你已经实现复杂度为O(n)的解法,尝试使用更为精妙的分治法求解。 Solution1.0 classSolution{ public: intmaxSubArray(vector<int>&nums){ intsize=nums.size(); if(size==0)return0; vector<int>sum;sum.resize(size); sum[0]=nums[0]; for(inti=1;i<size;++i){ sum[i]=max(sum[i-1]+nums[i],nums[i]); } return*max_element(sum.begin(),sum.end()); } }; 复制 思路

  • 基于 Google-S2 的地理相册服务实现及应用

    马蜂窝技术原创内容,更多干货请关注公众号:mfwtech 随着智能手机存储容量的增大,以及相册备份技术的普及,我们可以随时随地用手机影像记录生活,在手机中存储几千张甚至上万张照片已经是很常见的事情。但另一方面,当我们想从这么多张照片中去找到一张,也是一件麻烦事。 马蜂窝作为旅行玩乐平台,希望实现「会玩的人」与「好玩的事」之间的连接。众多旅行爱好者在这里记录和分享他们的旅行记忆,使马蜂窝在旅游UGC领域累积了大量内容。因此,不断优化用户在发布内容时的体验是我们一直努力的主向。 用照片、视频记录旅行是最直接的方式。本文将介绍马蜂窝如何通过App地理相册空间索引的应用,为用户提供直观、好用的图片分享服务。 Part.1应用场景和需求 要想让用户快速地找到想要分享的照片/视频,我们需要一个有效且合理的筛选手段,对用户的相册进行聚合、排序,提升用户依托相册去分享和记录生活时易用性和便捷性。 首先要确定聚合排序的筛选维度。照片的地理位置就是最直观的分类维度;同时,记录最近发生的事情符合用户的发布行为习惯。因此我们方案要满足的需求是: 根据目的地和时间,对用户相册进行聚合、排序; 基于某个地理

  • 给洁洁的建议

    仔细看了洁洁的意见,然后发现确实有点惭愧hh,然后以后慢慢改正 好像没什么特别的建议想到,希望觉得我回信息不及时或者敷衍的时候不要生气,hhh大部分时候是没看到,不然就是在打游戏,很偶尔是心情很烦不太想说话~ 多给我点空间有时候真的不小心没有照顾到你的情绪~ 然后不要怀疑我们对彼此的爱好嘛一直一直都很爱少惹你生气不然我自己也会心态爆炸,加上现在那么忙 所以就希望你稍微钝一点 会喜欢你霸气一点?比如说在我管不住自己的时候直接帮我做决定?md我真的麻烦事多 然后就没有啦开开心心的就好啦

  • aws安装

    1 在Python虚拟环境中安装AWSCLI  pipinstallawscli--user复制   2  查看当前版本 aws--version 3  卸载 pipuninstallawscli   4  配置AWSCLI awsconfigure填写id,secret和region,[以下是瞎填的]复制 AWSAccessKeyID[None]:AKIAIOSFODNN7EXAMPLE AWSSecretAccessKey[None]:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY Defaultregionname[None]:us-east-2 Defaultoutputformat[None]:json复制 然后可以去这里更改:vi~/.aws/configvi.aws/credentials复制   5访问s3:需要输入endpoint 每次需要输入 awss3--endpoint=http://*****--prof

  • Wireshark抓包分析TCP 3次握手、4次挥手过程

    Wireshark简介 更多有关Wireshark的教程、软件下载等,请见:http://www.52im.net/thread-259-1-1.html,本文只作简要介绍。 1Wireshark是什么? Wireshark是最著名的网络通讯抓包分析工具。功能十分强大,可以截取各种网络封包,显示网络封包的详细信息。你可以把网络包分析工具当成是一种用来测量有什么东西从网线上进出的测量工具,就好像使电工用来测量进入电信的电量的电度表一样(当然比那个更高级)。过去的此类工具要么是过于昂贵,要么是属于某人私有,或者是二者兼顾。Wireshark出现以后,这种现状得以改变。Wireshark可能算得上是今天能使用的最好的开源网络分析通讯抓包分析工具软件。 2Wireshark的使用对象 Wireshark可以用在许多场合下,以下只是典型的使用对象举例: 用来解决网络问题网络管理员; 用来检测安全隐患网络安全工程师; 用来测试诸如即时通讯软件的协议执行情况的开发人员; 用来学习网络通讯协议的学习、教师或爱好者。 使用wireshark的人必须了解网络协议,否则就看不懂wireshark

  • mysql远程连接出现 ERROR 2003 (HY000): Can&#39;t connect to MySQL server on IP

    修改了如下两个位置,解决了这个问题: 修改/etc/mysql/my.cof配置文件:因为mysql默认只允许本机连接 修改远程连接用户权限:远程连接的用户被设置为不允许远程连接 首先修改/etc/mysql/my.cof,将bind-address一行注释掉。该参数表示mysql只监听来自该地址的连接请求。 修改远程连接用户的权限: 2.1.其次修改远程连接的用户权限。在mysql数据库的user表中可以看到,有一个叫host的字段,可以增加或者修改一个该远程连接用户的host值为%,表示通配所有ip,也就是允许所有ip可连接。 2.2.使用sql来增加一条记录:GRANTALLPRIVILEGESON*.*TO'username'@'%'IDENTIFIEDBY'mypassword'WITHGRANTOPTION; 最后重启mysql: servicemysqlrestartor/etc/init.d/mysqlrestart

  • [LeetCode] 215. 数组中的第K个最大元素

    题目链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/) 题目描述: 在未排序的数组中找到第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。 示例: 示例1: 输入:[3,2,1,5,6,4]和k=2 输出:5 复制 示例2: 输入:[3,2,3,1,2,4,5,5,6]和k=4 输出:4 复制 说明: 你可以假设k总是有效的,且1≤k≤数组的长度。 思路: 排序题 思路一:\(nlog(n)\)排序 思路二:\(nlog(k)\)堆排序 库函数 手写堆排 思路三:平均时间\(O(n)\),最差\(O(n^2)\)部分的快排 快排每次可以固定一个数位置,只需要判断是否在要找的位置上就可以了! 代码: 思路一:排序 classSolution: deffindKthLargest(self,nums:List[int],k:int)->int: returnsorted(nums,reverse=True)[k-1] 复制 思路二:堆排序 1,库函数

  • 360浏览器兼容模式下IE内核版本

    问题 最近在跟客户演示系统时,自己电脑IE11下好好的,我们web系统最低支持到IE9。在客户电脑上,IE9浏览器下可以正常浏览,但是360兼容模式下,页面什么也不显示。 通过F12调试工具发现,360浏览器默认使用的并不是用户电脑上的IE9模式,而是IE9的兼容模式,调整为IE模式可以正常显示。 IE兼容性列表 通过检查IE浏览器菜单发现,IE浏览器是可以设置兼容性列表的。通过IE的设置-》兼容性设置,可以添加指定网站使用兼容性视图。 刚开始以为是360浏览器读取了IE的兼容性列表,但是客户IE中上并没有针对我们系统的兼容性设置。 360兼容性列表 于是想到应该是360浏览器保存了自己的兼容性列表,但是一搜兼容性,都是360极速模式、兼容模式的切换。在360的设置里面找了一遍,也没有收获。最后,在这里找到了答案。原来360浏览器的兼容性列表设置,在页面的右键菜单中。更多IE内核版本设置也可以参考链接中的内容。 搞定!!!

  • Mac上配置maven+eclipse+spark开发环境

    1、安装jdk 2、下载scala-ide。官网:http://scala-ide.org 3、安装maven 4、在eclipse中,配置maven的安装了路径。偏好设置--->maven--->installpath 5、修改maven的镜像文件,即setting.txt中的mirror。具体修改为如下: <mirrors> <mirror> <id>alimaven</id> <name>aliyunmaven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> <!--mirror |Specifiesarepositorymirrorsitetouseinsteadofagivenrepository.Therepositorythat |thismirrors

  • macrotask 和 microtask 的本质和理解

      浏览器的事件循环分为macrotask和microtask,浏览器先从macrotask取出一个任务执行,再执行microtask内的所有任务,接着又去macrotask取出一个任务执行,这样一次循环。      marcotask的本质是浏览器多个线程之间通信的一个消息队列;在chrome里,每个页面都对应一个进程,该进程又有多个线程,比如js线程、渲染线程、io线程、网络线程、定时器线程等等,这些线程之间的通信是通过向对象的任务队列中添加一个任务(postTask)来实现的;   浏览器的各种线程都是常驻线程,他们运行在一个for死循环里面,每个线程都有属于自己的若干任务队列,线程自己或者其它线程都可能通过postTask向这些任务队列添加任务,这些线程会不断的从自己的任务队列中取出任务执行,或者把处于睡眠状态直到设定的时间或者是有人postTask的时候把它唤醒;     microtask是确确实实存在的一个队列,microtask是属于当前线程的,而不是其他线程postTask过来的任务。只是延迟执行了而已,比如Promise.then、mutationObse

  • 程序员之间的相处

        都说程序员是老实憨厚的,其实现在看来真的不是这样。和其他行业一样,有人的地方就有江湖,有时候产生矛盾其实很容易的。有些时候该让,有些时候不能让。要学会看人识人,知道哪些人是可以在你困窘的时候帮你一把的,哪些人是不会帮你的,然后善待那些帮你的人,感恩

相关推荐

推荐阅读