最近动态

编程

微信服务号的消息处理

新产品会和微信公众号有交互,所以就来尝尝鲜,做一做微信公众号的各种东西.

首先:注册,认证,bla bla bla,设置一堆东西

在获得了开发权限之后,就可以仔细阅读开发文档了.

和微信的交互有两种:

  1. 服务器给微信发送消息
  2. 微信给服务器发送消息

说说他们的区别.

服务器给微信发消息,很方便,发表单格式的就行了,微信回复的是json格式的

微信服务器主动给服务器发消息,就很恶心了.

  1. 如果在配置页面设置了消息模式是加密的,那么收到了微信的消息之后需要先对包进行解密,才能得知微信发送的消息的确切内容.
  2. 微信的每次请求,都需要按照和它一样的变态格式回复.
  3. 还得验证验证消息到底是不是微信发的~

先来看看微信给服务器发的是什么样子的东西

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>

哦,这个是没加密的,加密的更难看…

应该用正则来提取内容吧,我把他们都写了出来,方便方便

REGEX_TOUSERNAME = r'\<ToUserName\>\<\!\[CDATA\[(.*)\]\]\>\<\/ToUserName\>'
REGEX_FROMUSERNAME = r'\<FromUserName\>\<\!\[CDATA\[(.*)\]\]\>\<\/FromUserName\>'
REGEX_MSGTYPE = r'\<MsgType\>\<\!\[CDATA\[(.*)\]\]\>\<\/MsgType\>'
REGEX_EVENT = r'\<Event\>\<\!\[CDATA\[(.*)\]\]\>\<\/Event\>'
REGEX_EVENT_KEY = r'\<EventKey\>\<\!\[CDATA\[(.*)\]\]\>\<\/EventKey\>'
REGEX_SCANTYPE = r'\<ScanType\>\<\!\[CDATA\[(.*)\]\]\>\<\/ScanType\>'
REGEX_SCANRESULT = r'\<ScanResult\>\<\!\[CDATA\[(.*)\]\]\>\<\/ScanResult\>'
REGEX_CREATETIME = r'\<CreateTime\>(.*)\<\/CreateTime\>'
REGEX_CONTENT = r'\<Content\>\<\!\[CDATA\[(.*)\]\]\>\<\/Content\>'

还傻乎乎的搞了个类来解析这坨东西

class wechat_xml_object(object):
    def __init__(self, xml):
        self.origin = str(xml)

    @property
    def toUserName(self):
        return self.returnValueForKey(REGEX_TOUSERNAME)

    @property
    def fromUserName(self):
        return self.returnValueForKey(REGEX_FROMUSERNAME)

    @property
    def msgType(self):
        return self.returnValueForKey(REGEX_MSGTYPE)

    @property
    def event(self):
        return self.returnValueForKey(REGEX_EVENT)

    @property
    def eventKey(self):
        return self.returnValueForKey(REGEX_EVENT_KEY)

    @property
    def scanType(self):
        return self.returnValueForKey(REGEX_SCANTYPE)

    @property
    def scanResult(self):
        return self.returnValueForKey(REGEX_SCANRESULT)

    @property
    def createTime(self):
        return self.returnValueForKey(REGEX_CREATETIME)

    @property
    def content(self):
        return self.returnValueForKey(REGEX_CONTENT)

    def returnValueForKey(self, regex):
        match = re.search(regex,self.origin)
        if match:
            return match.group(1)
        else:
            return None

虽然我知道有kissXML这种神器,但是我得装……

上面是把明文的XML解包出来,现在我们把想回复的数据给封装起来

class wechat_xml_builder(object):
    def __init__(self, data_type):
        self.type = data_type
        self.content = ''
        self.contains = []

    def addObject(self, key, value, data_mark):
        if key in self.contains:
            return False
        if data_mark:
            self.content += '<{0}><![CDATA[{1}]]></{2}>'.format(key, value, key)
        else:
            self.content += '<{0}>{1}</{2}>'.format(key, value, key)
        self.contains.append(key)
        return True

    def add_default_from(self, dictionary):
        fromUser = dictionary['toUser']
        openid = dictionary['openid']
        createTime = dictionary['createTime']
        self.addObject('ToUserName', openid, True)
        self.addObject('FromUserName', fromUser, True)
        self.addObject('CreateTime', createTime, False)

    def exportString(self):
        return '<xml>' + self.content + '</xml>'

我感觉这个类用起来还是蛮简单的.

至于说加密和解密,微信还是很良心的提供了一个库,可以直接操作.

下次再整理一下微信开发中其他的坑儿吧

阅读剩下更多

编程

ios 命令行单元测试

在开发iOS大项目的时候,由于模块太多,每个功能的模块也太多,在后续测试调试的时候,遇见了bug,就会花比较长的时间去定位bug所在的类或者所在的函数.如果使用了单元测试便可以缩小查找bug的范围.

XCode自带单元测试的命令行工具,可以编写UnitTest文件来自动测试工程,下面来介绍一下它的一些些用法.

首先得确定有xcodebuild命令(跳过,都是iOS开发者,肯定装了XCode咯)

$xcodebuild

肯定没这么简单,假设当前目录是有XCode的工程的,那么这个命令就会执行与在xcode里面点击build一样的效果.

使用xcodebuild运行测试

xcodebuild 命令就是执行了 XCode 里面的build,不过这个命令有一些其他的参数,用法太多这儿就不解释了.总之给他加点儿不同的参数就可以做不同的事情.使用 test 来测试.用-scheme指定操作的scheme.用 -destination 指定target.要在本地 iPhone 5模拟机 “iPhone 5” 测试某个工程的某个测试,使用如下命令来指定目标和架构:

xcodebuild test -project rct6updater.xcodeproj -scheme rct6updaterTest -destination 'platform=iOS ,name=iPhone 5'

如果想对真机操作,可以按照名称或id.比如,我的测试机叫做”VikingWarlock 5”,可以这样来测试代码:

xcodebuild test -workspace xuanwheel/xuanwheel.xcworkspace -scheme xuanwheelTests -destination 'platform=iOS,name=VikingWarlock 5'

测试也可以在 iOS模拟器上运行.使用模拟器可以应对不同的外形因素和操作系统版本.例如:

xcodebuild test -workspace xuanwheel/xuanwheel.xcworkspace -scheme xuanwheelTests -destination 'platform=iOS Simulator,name=iPhone,0S=7.0' -destination 

如果测试失败,xcodebuild 会有红色的 FAIL 提示,修改修改测试的代码,多加一些提醒,这样可以更方便的定位错误点.

等下

之前是-project的,怎么突然使用了-workspace嘞?因为我的工程使用cocoaPods了,所以测试的时候要使用workspace才行.

阅读剩下更多

编程

Sublime 开发arduino

把Sublime改装成arduino的IDE

参加一个物联网比赛,它要求使用的开发板是基于Arduino的.可是,Arduino自己做的IDE简直难过死了,没有自动不全,也不能输入中文所以我想了一下,强大的sublime一定是有arduino的插件的!

安装Sublime

Sublime很牛逼,三个平台都有,百度上面一搜,去官网下载就好了,安装也不麻烦,所以就不说了

安装package-control

Sublime 有两个发行版Sublime Text 2 和 Sublime Text 3
针对这两个不同的版本方法也是不一样的

  1. Ctrl(Command) + ~ 呼出命令行
  2. 直接把下面的代码往里面怼,然后按Enter(Return)

Sublime Text 2 的安装方法:

import urllib2,os; pf='Package Control.sublime-package'; ipp =sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener(urllib2.ProxyHandler( ))); open( os.path.join( ipp, pf),'wb' ).write( urllib2.urlopen('http://sublime.wbond.net/' +pf.replace( '','%20' )).read()); print( 'Please restart Sublime Text to finish installation')

Sublime Text 3 的安装方法:

import urllib.request,os; pf = 'Package Control.sublime-package'; ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf),'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' +pf.replace(' ','%20')).read())

原来都是python语句(我总觉得sublime text的作者一定钟爱python)

安装stino

  1. Crtl+Shift+P 打开另一种命令行
  2. 输入Package Control: Add Repository,按个Enter(Return)
  3. 输入Stino的开源地址 https://github.com/gepd/Stino/tree/new-stino,按个Enter(Return)
  4. Ctrl+Shift+P 再一遍,输入Package Control: Install Package
  5. 等他更新完所有的源之后,输入stino,安装就好啦

后续

这个stino是可以代替arduino来进行交叉编译&上传代码的,不过这个功能必须要求Arduino IDE在当前平台也支持编译和上传某种板子(比赛用的板子就不支持Linux下的Arduino…)

stino安装完毕之后是需要选择Arduino IDE的安装位置,据说不要使用最新的Arduino,因为stino好像是不支持的.

小秘密

我感觉stino除了加了自动补全,以及一些基本arduino的语法补全之外,并没有什么特点.假设工程中需要调用其他的文件,其他的库,还是用的不爽……

阅读剩下更多

编程

BLE速度踏频公有协议

BLE(Bluetooth Low Energy)

不知道从哪一年开始,BLE突然火了起来,可能是苹果推动的iBeacon,推了BLE一把吧

BLE模块越做越小,越做越省点,于是他们就纷纷往智能硬件上面去集成了,比如说什么手环啊,码表啊,门锁,窗帘啊,灯啊,炫轮啊,之类的.

How does it work

这里不是说BLE在底层如何工作,只是从上层软件开发的角度,讲讲BLE怎么工作

BLE必须提到的几个名词

  1. peripheral
  2. central
  3. service
  4. characteristic
  5. UUID

Peripheral

传说中的外设,也就是那些个手环啊,码表啊,炫轮啊之类的东西,他们在不停地广播自己存在的信号,可以让别人知道自己存在,自己的名字,自己有些什么Service.别人也可以根据这个广播计算以下RSSI(信号强度)

Central

暂且叫他主机吧,因为在定义中,并不是叫Peripheral和Central,而是Master和Slave(太难听了,还是使用iOS中的外设中心吧).

Central可以接收到广播帧,并且知道它的Mac地址啊,拥有哪些Service啊,名字啊……

Service

服务,假设一个蓝牙可以提供很多信息,比如说,电量啊,心率啊,速度啊,还有自定义的一些数据.如果通过数据帧头来区分他们,会非常的麻烦.所以BLE有Service这个概念,一个Service负责一件事情,清晰明了.

Characteristic

特征值,每个服务可以拥有多个特征值,每个特征值都有权限,比如Read,Write,Write Without Response,Notify……

UUID

好吧,这么多东西,怎么标示嘞?用UUID咯…

BLE有专用UUID是16位的,然而标准的UUID是128位的.

总结一下

每一个外设(Peripheral)可以拥有很多的服务(Service),每一个服务(Service)可以拥有多个特征值(Characteristic),使用UUID来确定Service和Characteristic.

说说公有协议

由于BLE的Service和Characteristic的UUID是16位的,那就说有很多很多很多的UUID可以被定义.选择太多,就容易出乱子.所以大概是IEEE还是IEC还是SIG之类的组织专门定了一大堆公有协议

这个链接里面的Service是他们定的,貌似已经被大家接受了.

速度和踏频

为什么只说速度与踏频的公有协议呢?

因为我们刚好在做这个……

Service UUID: 0x1816
Characteristic UUID: 0x2A5B (至少得有Notify,Read权限)

有了这两个东西,你的App或者其他智能硬件就可以进行过滤扫描和连接了

具体协议

Flag(必须):8位
    0x01==(速度数据)
    0x02==(踏频数据)
    0x03= (速度数据+踏频数据)
速度数据:
    32位:累计轮胎圈数[溢出清零]
    16位:时间(精确到1/1024秒)[溢出清零]
踏频数据:
    16位:累计曲柄圈数[溢出清零]
    16位:时间(精确到1/1024秒)[溢出清零]

举个例子

轮子在3.7353秒转动了103圈,曲柄在54.1093秒转动了202

03 67 00 00 00 f1 0e 00 ca d8 70

阅读剩下更多

编程

删除静态库中的静态库~

iOS静态库开发的故事

假设我们要做一个SDK给别人用,有两个选择,framework包,a包.他们有啥区别?framework包里面可以包含图片资源.a包里面只能是纯代码.所以a文件的容量真的很小很小.

万一,我们制作静态库的时候调用了第三方库,在打包的时候,如果不把这些第三方库去掉,会有什么效果呢?

使用我们SDK的人如果也使用了相同的第三方库,就会导致在编译的时候,出现duplicate信号,因为两个相同的类出现了,所以呢,如果一定要使用a包,只能手动的将包内的第三方库给去掉.

OK, 我们来看看删掉一个.a静态库中的某个第三方静态库需要怎么搞

Context

我们做了一个.a静态库,其中包含了

Masonary
JFMinimalNotification
FCFileManager
.....

第一步:

lipo * -thin [platform] dir/new.a

platform是平台,什么x86啊,arm之类的

ar -t dir/new.a

解压出来

cd dir && ar xv new.a

跳转到那个文件夹

rm *MAS*
rm JF*
rm ...

删啊删啊删

cd ..
ar rcs lib_1.a dir/*.o 

重新再打包成lib_1.a

lipo -create ... -output new_clean_static_lib.a

最后生成多平台的静态库


这有什么问题嘛?

嗯,你发布的SDK肯定是多平台的,也就是说,你需要有多少个平台,上面的事情就得做多少次~~

So,我写了一个Python脚本专门来解决这个难过的事情,VKRemove

Function 1

python VKRemove.py -lp xxx.a

返回这个静态库里面包含的平台

This library contains:i386 armv7 x86_64 arm64

Function 2

python VKRemove.py -lb xxx.a

返回这个静态库里面所有的库

...'View+MASAdditions.o', 'ViewController+MASAdditions.o', 'XuanWheelBluetoothManager.o'...

感觉很高端了对吧?

Function 3

python VKRemove.py -i XuanWheelSDK.a -rm FCFileManager HMSegmentedControl- JFMinimalNotification   UIView+Round UIImage+ImageEffects.o MAS

这会生成一个xxx.a.new,它包含了之前所有的平台,并且去掉了指定的所有第三方库.

感觉更高端了吧?

Function 4

python VKRemove.py -i XuanWheelSDK.a -from clear.txt

每次都输入那么长的命令太难过了,不如从文件输入吧~

当然咯,Function 3中的-是干什么用的,可以直接去Github上面看,虽然是英文的~

阅读剩下更多

日记

社会信用卡已透支

古时候摔倒了,摔伤了的人,会被路人扶起来,被好心人带回家疗伤.待他伤好之后,会感激这个救助他的好心人.现在大家看到躺着的人,不敢去扶,不敢去救助那个好心人,因为那个地上躺着的人,不知道是真的弱势群体,还是一个伪弱势群体.

陌生人手机没电了,急着需要联系他人,问你借用一下手机,看起来并没有什么问题,但是他可能会假装打电话最后骗走你的手机.

有人问你要钱回家,并答应到家之后把钱寄给你,这也有可能是骗你的.

人之初,性本善.我们每个人都是善良的,都有一种本能想去帮助其他人,帮助那些需要帮助的人,帮助弱势群体.可是,总有些自以为聪明的人能看到“商机”,利用人们本来的善,来牟利来做恶.让人与人之间变的不信任,让我们看不清这个世界.

可能会有一日,现在幸运着的我们,也会变成一个不幸的人,会真的在路上摔倒摔晕,会真的需要借用一下手机,会真的需要一个好心人的救助,可是在那个时候,人与人之间的信任还存在嘛?可能早就被那些小人们刷透支了吧.

以上全是吐槽…

要说这现象已经有无数的人分析过了,至于怎么解决.官方的做法是,大力传播正能量,让大家有信心,相信世界还是美好的,人与人之间还是可以信任的,坏人还是少的…我觉得呢,应该和老炮儿一样,能帮忙就帮一下.没被骗,心里开心;被骗了,就当是积个德.

扶了人被讹,就认命吧,就当你是攒人品,谁要你倒霉碰到个王八犊子呢?

借手机打电话被骗走,就认了吧,就当是攒人品,谁让那王八犊子没手机还刚好喜欢你的呢?

对于执法部门,我觉得对待这种案子不能就这么不了了之,就应该翻录像,调集各种资源查出真相!暂且不说什么纳税人的事儿,这些坏人做的不仅仅是骗了些小钱的事儿,而是在慢性的破坏社会,一点一点的让社会笼罩在一片不信任之中.

我自以为是个有爱心的人,但是相比起来我更爱手机…所以,摔倒了的人我会扶,但是想要我借你手机用,想都不要想

阅读剩下更多

日记

绍兴囧事们

离家37小时,还是发生了很多的囧事的.

比如说闹钟设晚了1小时

比如说为了纸巾去KFC买了一份粥

比如说鑫鑫带了一副三国杀没动过

比如说硕硕带了电脑连机都没有开过

比如说仑仑用百度地图查到的公交车站总是换名字

比如说兔兔一口气睡了12+小时

比如说光光带的装满礼物的行李箱被塞满了大家脱下来的衣服

比如说燕燕一直在做”小姨妈”

比如说彪彪竟然在游乐园里得了结膜炎

比如说猪猪被小朋友摸了猪屁股

除了上述个人囧事,其实还有一些组队完成的囧事,比如说

“两个欧巴好和谐哟,在一起”,这种话离开了科大还是第一次听到,没想到现在的小朋友那么牛逼,懂得挺多的嘛

9个成年人陪一个小朋友去儿童乐园,结果还是成年人玩得多,据说,有个成年人还玩哭了

打扑克,两副牌出现了4个大王,还打得挺high的

一个通知父爱泛滥把所有叫他”粑比”的小伙伴都当做孩子一样

我们住到了一个打开门就能发现地上有各种”上门服务”的小卡片的酒店,虽然大家都很想打一个电话试试看,但是都没有胆子

三个小伙伴貌似花了2.1元坐了相同路线的公交车,便高兴了很久,一直在算比那些打车的小伙伴赚了多少.不过,好像本来可以两个人不用付钱的嘛.

由于床被扑克占领了,我只能在地上眯一会,结果有个同志做俯卧撑,我还以为地震了,立刻吓尿了.

最精彩的当然是最后的速度与激情咯,具体的就不说了,一句话总结就是”打车打得早,不如打得巧”!

阅读剩下更多

返回顶部