iOS-使用SoftAP完成与智能硬件的交互
首先要说一声抱歉,昨天在写完bonjour的时候应该加把劲把这篇也写好的,但是……渣渣向你丢来了一个dota2,你感到时光飞逝,dota2效果拔群。
呃,总而言之,先说一下SoftAP的概念吧。
根据百度知道的说法,SoftAP模式是一种通过无线网卡,使用专用软件在PC上实现AP功能的技术,它可以取代无线网络中的AP(Access Point,无线接入点),从而会降低无线组网的成本。也就是可以把载体作为无线接入点,让电脑、手机或者其他上网设备的无线网连接到载体上,然后通过载体的网络(GPRS或者3G)上网。
浅显地来说,一个设备可以发出Wi-Fi信号,从而让其他手机啊电脑啊什么的连到它的Wi-Fi上去,达到局域网的效果,然后,利用局域网就可以联机……啊不,开发功能了。
我需要实现的功能也是跟上一篇一样,在将wifi账号密码交付给智能硬件的同时获取它的mac地址。
没错,同样的功能,两种实现方式。
在很多以交互为概念的领域中,这是非常重要的,毕竟,当你只有一种方法达成目的时总会有用户因为各种原因而没办法如你想象的一样走在你设计的路上,那么,在这个时候,多一条路就是不错的解决办法。
那么,在DEMO之前你需要了解两样东西,一是,让智能硬件如下图这样:
让它的wifi信号显示在手机的wifi列表中并不属于我们的范畴中,这是硬件工程师的工作,所以,如果你们的智能硬件没有这样的功能就不用往下看了。
二是,我们需要一个socket,是的,不管是ios自带的socket还是第三方的asyncsocket(大部分情况下最好使用asyncsocket,它的代码观赏性总是比原生的更佳,更何况,谁不喜欢异步呢?)
如果是第一次接触socket的同学也不必担心,前人插下的大树早已形成一片绿荫,无论是fuck baidu还是fuck google你都能在第一页找到你需要的完备代码,细细研读半个小时就能心领神会。
总而言之,你对asyncsocket的封装代码后露出头的需要有以下几个部分
@interface BSSocketServe : NSObject
//一个连接成功后的block回调,当然,代理或者其他什么随便啦,你要用通知我都没意见。
@property(copy,nonatomic)void (^CallBackBlock)(BOOL Success);
//一个信息回调,这个需要与你们的硬件工程师协定,当硬件得到它想要的数据后返回给你什么,这里我得到的是mac地址。
@property(copy,nonatomic)void (^MessageBlock)(NSString *message);
//单例或者其他你认为更好的选择
+(instancetype)shareSocketServe;
//开始连接吧,切记在正确的环境下连接,不然你很可能得不到想要的结果。
-(void)startSocket;
//通常,我们需要切断连接的方法。
-(void)cutOffSocket;
//whatever
- (void)sendMessage:(id)message;
-(void)sendSSID:(NSString *)ssid AndPWD:(NSString *)pwd;
@end
然后它们的实现是这样的
#import "BSSocketServe.h"
#import "AsyncSocket.h"
//你想要与之对话对象的ip地址以及它的端口号,在与硬件交流中通常是固定的,但你也可以从外界去取它。
#define HOST @"20.16.1.1"
#define PORT 21601
#define TIME_OUT 20
typedef enum {
SocketOffLineByServe ,
SocketOffLineByUser ,
SocketOffLineByWiFiCut
}SocketOffLineBy;
@interface BSSocketServe ()<AsyncSocketDelegate>
@property(strong,nonatomic)AsyncSocket *socket;
@end
@implementation BSSocketServe
+(instancetype)shareSocketServe{
static BSSocketServe * socket = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
socket = [[[self class] alloc]init];
});
return socket;
}
//开始连接
-(void)startSocket{
self.socket = [[AsyncSocket alloc]initWithDelegate:self];
[self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
if (![self SocketOpen:HOST port:PORT]) {
}
}
//切断连接
-(void)cutOffSocket{
[self.socket disconnect];
}
-(NSInteger)SocketOpen:(NSString *)addr port:(NSInteger)port{
if (![self.socket isConnected]) {
NSError *error = nil;
[self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
}
return 0;
}
//asyncsocket的代理方法,当你成功连接时它会调用这个方法
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
// NSLog(@"成功连接");
self.CallBackBlock(YES);
}
-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{
NSLog(@" willDisconnectWithError %ld err = %@",sock.userData,[err description]);
if (err.code == 57) {
self.socket.userData = SocketOffLineByWiFiCut;
}
}
-(void)onSocketDidDisconnect:(AsyncSocket *)sock{
NSLog(@"7878 sorry the connect is failure %ld",sock.userData);
if (sock.userData == SocketOffLineByUser) {
// 服务器掉线,重连
[self startSocket];
}
else if (sock.userData == SocketOffLineByUser) {
// 如果由用户断开,不进行重连
return;
}else if (sock.userData == SocketOffLineByWiFiCut) {
// wifi断开,不进行重连
return;
}
}
//向服务器发送数据
-(void)sendMessage:(id)message
{
if ([message isKindOfClass:[NSString class]]) {
NSData *cmdData = [message dataUsingEncoding:NSASCIIStringEncoding];
[self.socket writeData:cmdData withTimeout:-1 tag:1];
}else{
[self.socket writeData:message withTimeout:-1 tag:1];
}
}
//对ssid以及pwd再包装后发送信息
-(void)sendSSID:(NSString *)ssid AndPWD:(NSString *)pwd{
//对数据的再处理自行决定,请不要忘记调用上方的sendMessage
}
//发送消息成功之后回调
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
//读取消息
[self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:1024 tag:0];
}
//接受消息成功之后回调
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
self.MessageBlock(str);
}
@end
好了,准备工作结束了,我的工作也就几近完成了,接下来只需要
//你总是可以将它简化成三目运算符
if "你处于硬件为你提供的wifi网络中时"{
BSSocketServe.shareSocketServe().startSocket()
}else{
"提示用户选择硬件的wifi网络"
}
//如果连接成功,向硬件发送它想知道的东西
BSSocketServe.shareSocketServe().CallBackBlock = { (Success:Bool) ->() in
if Success{
BSSocketServe.shareSocketServe().sendSSID(ssid, andPWD: pwd)
}else{
print("连接失败")
}
}
//在信息回调里处理你得到的信息
BSSocketServe.shareSocketServe().MessageBlock = {[weak self] (message) in
self?.MAC = self?.getMacAdress(message)
BSSocketServe.shareSocketServe().cutOffSocket()
}