2017年终总结

2017像以往的任何一个年头一样,在挣扎和匆忙中过去了。
一月的时候,女儿出生了,令我无比幸福,因为只能和妻子两个人来照看孩子,有了孩子后,老婆性情大变,也开始了我结婚以来的抑郁时刻(我们相识10年,结婚6年)。
三月的时候我的母亲意外车祸去世了,我无比痛苦,开始时常会一个人默默流泪,想念我的母亲或者曾经的某刻时光,我感觉自己抑郁了,或者这本身只是老了的一种表现,我不得而知。
年底左右的时候,借钱和贷款买了地铁口的小产权,不知道是生活的一个进阶还是屈服,然而这个喜悦丝毫不能让我从老婆带来的抑郁中走出来。
由于只能我们两个抚养小孩,我上班她全职,再加上她对小孩近乎变态的怜爱和呵护,这让他筋疲力尽,异常暴躁,而我看在眼里,也只能默默忍受这一切的改变,毕竟她是为了女儿,而我因此要责怪她或者女儿,显然不可能。也许这是人生的必经阶段,也许这是婚姻的不可避免,我无可选择。
因为母亲去世,要打官司赔偿,只能把工作辞掉,准备做好持久战的准备,所以在处理完母亲的事故后,四月底重新入职到了现在的公司。
因为是曾经的同学的极力邀请,所以在据掉了一家以色列的初创公司后,开始了一年多的开发历程。
昨天还收到那个以色列公司的创始人的微信拜年,感觉时光匆匆。
目前的公司是北京公司的深圳分部,也就是初创公司,入职的时间也是新公司的注册成立时间,前期就几个主力人员,基本每个人负责一款独立的产品或者软件。
先是四月开始,要完成一款路由器的开发,因为以往软硬件的积累以及linux的开发经验,很快就从零开始完成一款基于openwrt的行业设备的软件开发,其中一半多的时间是梳理需求和设计业务场景和平台通讯接口协议,开发和测试差不多一半时间。但是因为商务订单的问题,这款演示和测试完成后就暂停了。
这期间,因为大家都没有开发过微信公众号,因为自己有后台开发的经验,就一个人主动承担了公司的微信服务公众号的后台开发,基于php的,一个多月就完成了设计和开发,期间为了按计划完成,取消了提前两个月预定的十一探亲机票,还好按计划完成,也算不枉取消机票的损失。但完成自我目标的喜悦完全可以忽略金钱的损失,内心很高兴。完成项目后,请假一周,回家探亲,让父亲看了下他的孙女,父亲不善言语,但知道他看到孙女很高兴。
11月的时候公司因为想争取一个NBIOT的项目,承诺快速给客户演示样机,又进入到了加班加点的样机开发中,后面还出差成都一周进行现场测试,实测下来NB在做定位tracker方面,目前的芯片方案和运营商服务还不是很成熟,后来测试完了后,因为还达不到GSM的移动稳定性,同时客户也是没有实际的业务订单,也只是想看看NB的效果,所以也只能暂告段落。
完成NB的演示后,就进入了政府的牧场项目中,目前的北京总公司资源很丰富,项目真多。这个项目是和内蒙政府做牧场的牲畜定位追踪和食品安全追溯系统。加班加点的在1月25完成第一期的实地场测。签署了第一批350万的订单,然后就紧接着迎来的农历新年放假。据说放假前,公司拿到了项目款,算是总算干了一个进账的项目吧。
放假期间要完成以下的任务:
1.整个系统的需求文档,因为我是整个项目的产品经理,所以需要统筹整体方案(硬件,平台,app)
2.产品的几个相关app原型和交互设计,年后主要做app的产品经理,将基本完成的硬件firmware的代码交接给其他开发同事。
3.现有硬件fireware的概要设计和详细设计
回来的路上开始看“创业维艰”,今天终于看完了,算是对这几天闲暇愧疚的一个慰藉吧,这是一本很好的书,希望有空能单独写一篇读书笔记。
还有一个小小的喜悦是拿到了驾照,工作这么多年来,一直都很忙,创业和上班,没有时间,今年因为考虑小孩的未来需要,终于下决心抽空把驾照考了。
这几天每天都是吃吃吃,每天都有相邻和亲戚来串门或者拜访,不得闲暇,今日有空,故记录流水账,以慰愧疚。

总的来说,因为自己做事的风格以及对自己的要求,工作都很忙,但今年格外忙,在加上母亲的意外和孩子的出生,2017是我人生中最煎熬的一年,希望未来越来越好。
特别感谢一直以来支持的朋友,如果没有你们一直以来的支持和关心,我可能在抑郁和压力中作出令人不敢想象的决定,在这里默默谢谢你们,也祝你们未来越来越好。

STM8 IWDG看门狗的使用说明

好久不搞stm8了,但朋友请教,还是帮忙确认下。主要是确认STM8的看门狗用法和喂狗时间问题,网上大把的代码样例,但是还是要刨根问底弄清楚细节,才可以用,否则就是埋雷。

大概的调用样例代码:

#define SYS_IWDG_OPEN        IWDG_KR=0xCC;
#define SYS_IWDG_FEED        IWDG_KR=0xAA;

void SystemIWDG_Config(void)   
{
    CLK_ICKCR|=S3;
    while((CLK_ICKCR&S4)==0);
    //STM8单片机需先执行0xCC指令,即先打开IWDG模块,否则IWDG工作不正常
    IWDG_KR=0xCC;                //启动看门狗
    IWDG_KR=0x55;                //使能模块访问
    IWDG_RLR=0xFF;               //溢出时间
    IWDG_PR=0x06;                //256分频 38000/256=148HZ T=6.7ms    
    IWDG_KR=0xAA;                //装载IWDG->RLR
}

代码的解释请参见以下的网络内容:

STM8独立看门狗介绍

独立看门狗模块可以用于解决处理器因为硬件或软件的故障所发生的错误。它由一个内部的128kHz的LSI阻容振荡器作为时钟源驱动,因此即使是主时钟失效时它仍然照常工作。

  • 独立看门狗功能说明
    图24是STM8独立看门狗模块的功能框图。
    当在键寄存器(IWDG_KR)中写入数值0xCC后,独立看门狗就被启动了,计数器开始从它的复位值0xFF开始递减计数,当计数减到0x00时就会产生一个复位信号(WDG RESET)。
    使用IWDG_PR和IWDG_RLR寄存器配置独立看门狗。IWDG_PR寄存器是用于选择驱动计数器时钟的预分频系数。每当KEY_REFRESH的数值(0xAA)写入到IWDG_KR寄存器时,独立看门狗将用IWDG_RLR的数值刷新计数器的内容,从而避免了产生看门狗的复位。
    IWDG_PR和IWDG_RLR寄存器具有写保护功能,要修改它们前,需首先在IWDG_KR寄存器写入KEY_ACCESS代码(0x55);在IWDG_KR写入0xAA将恢复写保护状态。

STM8_蜂鸣器功能图
(图24:STM8独立看门狗框图)

  • 硬件看门狗功能
    如果在IWDG_HW选择字节中使能了硬件看门狗的功能,在芯片上电时看门狗的功能被自动开启,如果软件不能及时操作键寄存器,则在计数器达到0x00时产生复位。关于选择字节的内容请参考数据手册中的说明。
  • 超时周期
    超时周期由计数器数值和时钟预分频器决定,下表列出了它们的数值。


(表26:STM8看门狗超时周期(假定计数器时钟为64kHz) )

键寄存器(IWDG_KR)

地址偏移值:0x00
复位值:未定义

STM8_键寄存器(IWDG_KR)

位7:0 KEY[7:0]:键值
软件必须在规定的时间内写入KEY_REFRESH数值,否则当计数器数值达到0时,看门狗会产生一个复位。
KEY_ENABLE数值=0xCC
写入KEY_ENABLE数值将启动IWDG。
KEY_REFRESH数值=0xAA
写入KEY_REFRESH数值将刷新IDDG。
KEY_ACCESS数值=0x55
写入KEY_ACCESS数值将允许对受保护的IWDG_PR和IWDG_RLR寄存器的操作

预分频寄存器(IWDG_PR)

地址偏移值:0x01
复位值:0x00

STM8_预分频寄存器(IWDG_PR)

位7:3 保留,必须保持为0。
位2:0 PR[2:0]:预分频系数
这些位是写保护的。它们用于指定对计数器时钟分频的分频系数。
000:分频系数=4
001:分频系数=8
010:分频系数=16
011:分频系数=32
100:分频系数=64
101:分频系数=128
110:分频系数=256
111:保留

重装载寄存器(IWDG_RLR)

地址偏移值:0x02
复位值:0xFF

STM8_重装载寄存器(IWDG_RLR)

位7:0 RL[7:0]:看门狗计数器重装载数值
这些位是写保护的(见14.2)。每次在IWDG_KR寄存器中写入0x
被传送到看门狗的计数器中,看门狗的计数器将重新从这个值开和时钟的预分频系数决定,见表26。

IWDG寄存器映像和复位数值


(表27:STM8 IWDG寄存器映像 )

 

官方手册原始内容,124页:

http://www.st.com/content/ccc/resource/technical/document/reference_manual/9a/1b/85/07/ca/eb/4f/dd/CD00190271.pdf/files/CD00190271.pdf/jcr:content/translations/en.CD00190271.pdf

本地下载备份:en.CD00190271

根据芯片手册中时钟的配置:

Watchdog timeout period

文章开头样例代码的看门狗最大喂狗时间大约1.725秒(38K时钟)

xcrun导致的pod更新失败

系统升级到最新的sierra后,执行pod update 失败:

zcj-macair:qinmi alex$ pod update
-bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad interpreter: No such file or directory
zcj-macair:qinmi alex$ brew install ryby
Updating Homebrew...
==> Using the sandbox
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
Error: git cannot be built with any available compilers.
Install GNU's GCC
  brew install gcc

Error: Git must be installed and in your PATH!
Error: No available formula with the name "ryby" 
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching taps...
Error: No formulae found in taps.

按照提示安装对应的程序时,进一步提示错误,发现是xcrun错误。

更新xcrun环境:xcode-select --install
更新ruby:brew install ruby
更新pod:gem install cocoapods

openwrt中添加mt7628an对sim7600ce的支持

按照模块的使用手册,我们知道设备的usb会虚拟出5个串口设备。
在openwrt中默认是支持usb转uart的驱动的,默认是可以支持此设备的,我们只要在menuconfig中选择相应的开关就可以完成支持

Kernel Modules → USB Support
<*> kmod-usb2
<*> kmod-usb-ohci
<*> kmod-usb-serial
                <*> kmod-usb-serial-option
                -*- kmod-usb-serial-wwan
<*> kmod-usb-core

ssh强制密钥登陆

在网路上有大量的扫描程序和爬虫在扫描肉鸡,其中一个最常用的方式就是扫描ssh权限。这种肉鸡主要用来【翻腔】或者DDOS或者挖矿等,总之是可以牟利的。

新注册的vps,还没多久就发现:

There were 2816 failed login attempts since the last successful login.

而避免被暴力的一种简单的方法就是强制密钥登陆。

  1. 创建密钥对
    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    按照流程走完后会在 ~/.ssh目录下看到id_rsa, id_rsa.pub文件 第一个是私有密钥 第二个是公有密钥。
  2. 将公钥的*.pub内容写入:.ssh/authorized_keys
    如果没有目录创建目录。
  3. 修改服务器配置 /etc/ssh/sshd_config
    PasswordAuthentication no 默认yes,改为no。是否允许使用基于密码的认证。
    (建议但非必选)
    GSSAPICleanupCredentials yes 默认no,改为yes。是否在用户退出登录后自动销毁用户凭证缓存
  4. 修改完后重启sshd服务
然后私钥就可以用来在客户端登录时使用,如果密钥没密码,就可以实现无密码登录了

APNs调试工具Knuff介绍

作为一个ios开发者,在你调试APNs时,正常的情况下你需要弄好证书给到后台的同事上线到测试环境,然后才能开始测试调试推送的相关功能。

如果这个过程遇到证书错误,后台代码错误,苹果变更接口等,等到能调试ios的功能,需要等到好久的时间。

那么ios可以独立调试APNs的相关功能吗?当然可以,Knuff就是一款简洁简单的推送调试工具。下面的以MAC的为介绍对象,其他平台的请自行理解。

软件界面如下:

Knuff功能说明

Custom:自定义模式,可以自行选择证书,我们测试自己的应用,就用这个模式

Knuff iOS: Knuff iOS表示使用Knuff的证书,直接推送给Knuff配套的ios应用。

Choose:选择推送的push证书,我们需要选择我们证书,关于如何生成正确的证书,请自行google。

Production:选择证书后,就会出现这个选择,production表示appstore证书,推送给appstore版本的APP。

Sandbox:表示开发调试的非AppStore版本。

Priority:测试时可随意选择。

Payload:表示要推送的报文,具体字段含义这里就不展开了,请自行了解。

Token:device token,在注册苹果 APNs服务时获取的。参考代码如下:

注册服务

[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings
                                                                             settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
                                                                             categories:nil]];

[[UIApplication sharedApplication] registerForRemoteNotifications];

回调事件
调用didRegisterForRemoteNotificationsWithDeviceToken

至此我们就可以开始测试了,通过这个工具我们就能轻易的测试我们的device token是否正确,测试我们生成的证书是否正确。给自己发送任意想测试的payload。

have fun!

APNs php客户端及静默推送

简介

关于APNs的工作原理,网上有大量的文章,建议学习apple的官方文档。通过APNs我们就可以通过服务器想APP推送想要的内容和事件。从而实现通知或者激活应用的目的。本文我们讲介绍如何搭建php的APNs推送以及如何实现静默推送。

APNs PHP 客户端

经过多方的验证,目前推荐这个:
https://github.com/immobiliare/ApnsPHP

证书验证

想要通过苹果服务器推送信息,必须要有合法的证书。很多人在推送这部分花了很多时间,很多情况是没搞清楚失败到底是代码的问题还是证书的问题。所以,我们需要先验证证书的合法和正确性。

推送时,我们要制作推送证书,我们要选择正确的类型,具体的制作过程可自行搜索,最终的证书类型如下:
push cert

Easy APNS Provider

先前我的文章推荐过Knuff,经过深入的实践,这里我推荐Easy APNS Provider,可以从MAC store下载。相比较Knuff,EAP更加的稳定强大。通过工具我们就可以先行验证证书的正确性,避免后面定位问题浪费更多的时间。
[2020.03.31更新]:另一款值得推荐的是: https://github.com/noodlewerk/NWPusher

在MAC上用客户端向苹果发送推送服务器请求时,我们选择上面安装的证书就可以了。
easy apns provider config

PHP服务器证书生成

上面我们讲了怎么选择正确的客户端证书,当我们使用php 服务器推送时,我们还要做些额外的工作:

  • 打开“钥匙串”程序,(证书助理->从证书颁发机构请求证书),只填邮箱和常用名称,ca不用填,然后保存.certSigningRequest文件到磁盘。
  • 在iOS Dev Center 点击App IDs进入App ID列表。
  • 为 App 开启 Push Notification 功能。(推送证书分为两个版本,一个是Development版,一个是Production版,分别对应开发证书和发布证书。)
  • 上传刚才生成的.certSigningRequest文件,生成aps_development.cer推送证书,双击安装。
  • 打开“钥匙串”程序,(选择登录与我的证书选项后)找到IOS Push Services那条.
  • 右键导出,存储为cert.p12,(输入密码P*d)。然后将该证书的折叠向下展开打开,导出“专用密钥”,存储为key.p12。
  • 接下来打开终端执行下面的命令,生成的ck.pem就是我们在php脚本中要使用的证书。
    #生成cert.pem
    openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12
    #生成key.pem(先输出导出key.p12时设置的密码P*d, 然后设置一个新的密码,如pushpwd,这个密码后面php推送时要设置)
    openssl pkcs12 -nocerts -out key.pem -in key.p12
    #合并成ck.pem
    cat cert.pem key.pem > ck.pem

    APNs PHP客户端配置

这个软件包的最新版本支持HTTP2,如果你的PHP的版本支持HTTP2,建议优先使用。开发包里面自带了几个sample,简单配置后基本就可以使用。这里我们以sample_push.php为测试对象。
sample push demo code

如图所示,配置要点如下:

  • 目标环境:sandbox还是production,对于appstore下载的目标,请选择ENVIRONMENT_PRODUCTION,对于开发中的版本,清选择ENVIRONMENT_SANDBOX
  • 证书:填写证书的相对路径,这里最好时按照上面的步骤验证通过的证书
  • 在上面的步骤中我们生成pem证书时,要求一个最少4位的密码,所以这个地方一定要设置密码,否则connect会失败
  • device token:这里是我们要推送的目标的token。

测试通过的返回如下:

Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Trying tls://gateway.sandbox.push.apple.com:2195... Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Connected to tls://gateway.sandbox.push.apple.com:2195. Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Sending messages queue, run #1: 1 message(s) left in queue. Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: STATUS: Sending message ID 1 [custom identifier: Message-Badge-3] (1/3): 167 bytes. Fri, 13 Jan 2017 13:31:36 +0100 ApnsPHP[15355]: INFO: Disconnected.

device token

在上面我们提到了设备的device token,那么调试阶段如何获取这个token呢?在我们发起了注册请求后,系统会触发相应的消息回调。相关的参考代码如下:

-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    //读取APNS token
    NSString* _deviceToken = [[[[deviceToken description]
        stringByReplacingOccurrencesOfString: @"<" withString: @""]
        stringByReplacingOccurrencesOfString: @">" withString: @""]
        stringByReplacingOccurrencesOfString: @" " withString: @""];
    QMLogDebug(@"apns token:%@",_deviceToken);
    NSUserDefaults * userDefault = [NSUserDefaults standardUserDefaults];
    [userDefault setObject:_deviceToken forKey:APNSTOKEN];
    [userDefault synchronize];
}

上面的deviceToken就获取了我们需要的token。这里的deviceToken是NSData对象,可以手动导出二进制,然后这个导出文件就可以在测试客户端中使用。

全部的证书

除了ck.pem证书,我们的项目还需要 entrust_root_certification_authority.pem 这个证书,一共两个证书。

静默推送

ios最新的版本中已经支持了静默推送,静默推送时,客户端会收到消息,执行相应的动作,但不会做任何给用户的提示。在普通的推送中我们可以通过如下的代码实现静默推送的效果:

{
  "aps" : {
    "badge" : 0
  }
}

但是苹果还是专门定义了一个开关来表示静默推送 "content-available" : 1,由于此开关优先级较低,在静默推送的报文中不能出现alert,sound 等,否则就会变成普通推送。

静默推送的payload如下:

{
  "aps" : {
    "content-available" : 1
  }
}

静默推送的前提:

  1. 只有app还在后台运行时,才能收到静默推送,否则推送了也没有用
  2. 跟普通推送类似,苹果对频率和到达性都不做保证。

参考:
How to generate a Push Notification certificate and download the Entrust Root Authority certificate

基于certbot的letsencrypt安装使用

起因

  • 前面的文章讲过,运营商环节会在用户加载内容的时候,在流中进行注入frame ,强行展示广告。
  • 如果你的server是给App提供web api的接口,由于苹果ATS的执行,你不得不所有接口都升级成HTTPS。

免费ssl证书

首选当时letsencrypt了,官方网站是:https://letsencrypt.org. 网上大把文章,但按照本人一贯的习惯还是去官网,避免被过时的信息误导,反而浪费更多的时间。
官方推荐的是cetrbot:https://certbot.eff.org/
根据本人的系统,实际的文档路径:https://certbot.eff.org/#centosrhel7-nginx

letsencrypt

安装

首先需要安装certbot:
默认centos7是不支持certot,你需要先安装EPEL:https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F
实际的安装包为:https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
下载后安装rpm。然后执行:

sudo yum install certbot

一路‘y’,安装完成:

Installed:
  certbot.noarch 0:0.9.3-1.el7

Dependency Installed:
  dialog.x86_64 0:1.2-4.20130523.el7                 pyOpenSSL.x86_64 0:0.13.1-3.el7                     python-cffi.x86_64 0:1.6.0-5.el7
  python-chardet.noarch 0:2.2.1-1.el7_1              python-enum34.noarch 0:1.0.4-1.el7                  python-idna.noarch 0:2.0-1.el7
  python-ipaddress.noarch 0:1.0.16-2.el7             python-ndg_httpsclient.noarch 0:0.3.2-1.el7         python-parsedatetime.noarch 0:1.5-3.el7
  python-ply.noarch 0:3.4-10.el7                     python-psutil.x86_64 0:2.2.1-1.el7                  python-pycparser.noarch 0:2.14-1.el7
  python-requests.noarch 0:2.6.0-1.el7_1             python-six.noarch 0:1.9.0-2.el7                     python-urllib3.noarch 0:1.10.2-2.el7_1
  python-zope-component.noarch 1:4.1.0-1.el7         python-zope-event.noarch 0:4.0.3-2.el7              python-zope-interface.x86_64 0:4.0.5-4.el7
  python2-acme.noarch 0:0.9.3-1.el7                  python2-certbot.noarch 0:0.9.3-1.el7                python2-configargparse.noarch 0:0.11.0-1.el7
  python2-cryptography.x86_64 0:1.3.1-3.el7          python2-dialog.noarch 0:3.3.0-6.el7                 python2-mock.noarch 0:1.0.1-9.el7
  python2-pyasn1.noarch 0:0.1.9-7.el7                python2-pyrfc3339.noarch 0:1.0-2.el7                pytz.noarch 0:2012d-5.el7

Complete!

开始

在已经有webserver运行的情况下,certbot推荐我们使用“webroot”插件。可以实现在不暂停web服务的情况下更新证书。

webroot:不需要停机你的web服务

certbot certonly --webroot -w AAA -d BBB

BBB是你要支持的域名,AAA是BBB当前已经可以访问的目录。

standalone:需要停机你当前服务器的80端口的服务

certbot certonly --standalone  -d xxx.com

以上每一条命令生成一个对立的目录,如果是多个域名就是合在一起的一个文件。如果要每个域名都生成独立的目录和文件,就要执行多次。

成功后:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/xxx/fullchain.pem. Your cert
   will expire on 2017-03-18. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

手动在nginx的conf中配置相关的路径就可以了:

ssl_certificate /etc/letsencrypt/live/xxx/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx/privkey.pem;

续期

certbot renew

撤销

证书没有过期的话,我们可以撤销:

[root@rxblog certbot-0.22.2]# ./certbot revoke --cert-path /etc/letsencrypt/archive/xxx.com/cert1.pem
Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Would you like to delete the cert(s) you just revoked?
-------------------------------------------------------------------------------
(Y)es (recommended)/(N)o: Y

-------------------------------------------------------------------------------
Deleted all files relating to certificate iwwenbo.com.
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
Congratulations! You have successfully revoked the certificate that was located
at /etc/letsencrypt/archive/iwwenbo.com/cert1.pem

-------------------------------------------------------------------------------

删除

如果证书已经过期了,我们只能删除了

certbot delete --cert-name example.com

OK,暂时告一段落。

关于苹果前后台定位的使用

其实主要就是要理解这两个函数的功能和适用场景:
startUpdatingLocation
startMonitoringSignificantLocationChanges

可以参看苹果的这个demo:https://developer.apple.com/library/content/samplecode/Regions/Introduction/Intro.html
理解了,自己改动下,就能实现强大的后台定位

2016.12.25:
了解更多的细节,可以参看这里,全部确认到了,基本就搞定了:
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html