最近项目中用到了iPad驱动硬件来工作,也就是智能硬件的实现。下面简单说下原理,详细说下socket,wifi通信,数据处理接收,发送,以及数据解析代码。

首先,来说下通信。因为硬件部件比较多,我们采取的是,iPad与主控板进行交换数据,主控板来与各硬件部件进行通信。看图:

 
image.png

其中,主控与零部件间及时通讯,零部件实时把状态上报给主控。当然,iPad与主控板也是及时通讯,主控需要每秒都上报给iPad各个硬件的当前状态,以供iPad可以实时监控各零部件并且显示不同的状态,比如“ipad上实时显示电冰箱的温度”。后面这黑体加粗才是我们iOS端要做的任务。涉及到
1.与主控建立连接,
2.并保持长链接,实时接收解析主控发来的零部件状态,
3.以及iPad给主控发指令来驱动硬件动作,比如“iPad发送指令让电灯关闭”。

与主控建立连接,我们用到的是GCDAsyncSocket这个类,github地址https://github.com/robbiehanson/CocoaAsyncSocket

//  Created by 王聪
// Copyright © 2018年 apple. All rights reserved.
#import "GCDAsyncSocket.h"
@property (nonatomic,strong) GCDAsyncSocket *clientSocket;
@property (nonatomic,assign) BOOL connected; - (void)setSocketData
{
if (self.clientSocket && self.clientSocket.isConnected) {
[self.clientSocket disconnect];
self.clientSocket = nil;
}
self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; NSError *error = nil;
self.connected = [self.clientSocket connectToHost:@"你的地址" onPort:@"你的端口号" viaInterface:nil withTimeout:20 error:&error];
}

连接成功之后会回调GCDAsyncSocketDelegate的连接成功的方法如下。

/**
* Called when a socket connects and is ready for reading and writing.
* The host parameter will be an IP address, not a DNS name.
**/
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
NSLog(@"连接成功,连接主机信息 %@",sock);
self.connected = YES;
// 连接后,可读取服务端的数据
[self.clientSocket readDataWithTimeout:-1 tag:1];
}

相对的,断开连接会调用如下回调

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(@"tcp连接断开,%@",err);
self.connected = NO;
}

连接成功了,下面读取data

/**
* Called when a socket has completed reading the requested data into memory.
* Not called if there is an error.
**/
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
[APPDELEGATE.clientSocket readDataWithTimeout:- 1 tag:1];
NSLog(@"接收到的数据%@",data);
}

接收到数据了,下面我们来发送指令控制硬件。
先来看下我们与主控约定的协议格式。

 
image.png
 
image.png

接下来看代码怎么来发送这个协议数据到主控。

//发送数据的方法
- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

那么我们就要构造出这个data,就可以实现发送数据到主控了。
下面介绍两种生成data的方法。

//发送指令
+ (void)sendData{
NSData *data = [SendDataOp returnSetData];
NSLog(@"发送数据Cmd_set%@----------", data.description);
[APPDELEGATE.clientSocket writeData:data withTimeout:-1 tag:0];
} //构造data
+ (NSData *)returnSetData
{
//方法1,创建bytes数组
// Byte bytes[8] = {0x11,0xff,0x11,0xff,0x03,0x02,0x01,0x28};//40转为26进制为0x28
// //想操作其中某位可以用下标找到并修改,比如想把最后一位"亮度"改为5
// bytes[7] = 0x05;
// NSData *data = [[NSData alloc] initWithBytes:bytes length:sizeof(bytes)]; //方法2,直接拼接data
NSMutableData *data = [NSMutableData data];
//表头
char head1 = 0x11;
[data appendBytes:&head1 length:1];
char head2 = 0xff;
[data appendBytes:&head2 length:1];
char head3 = 0x11;
[data appendBytes:&head3 length:1];
char head4 = 0xff;
[data appendBytes:&head4 length:1]; //长度
char length = 0x03;
[data appendBytes:&length length:1];
//灯泡号
char num = 0x02;
[data appendBytes:&num length:1]; //命令字
char cmd = 0x01;
[data appendBytes:&cmd length:1]; //灯泡的亮度
int lightness = 40;
[data appendData:[mathUtil convertHexStrToData:[mathUtil ToHex:lightness]]];//这一步是把亮度40转化为16进制字符串,然后16进制字符串转化为NSData。下面粘上这一部分转换的方法 //推荐方法2,直接可以调用方法转为NSData,而方法1需要手动将40换算为28再拼上去。 return data;
//即拼成了11 ff 11 ff 03 02 01 28
}

10进制转16进制

+(NSString *)ToHex:(long long int)tmpid

{

    NSString *nLetterValue;

    NSString *str =@"";

    long long int ttmpig;

    for (int i =0; i<9; i++) {

        ttmpig=tmpid%16;

        tmpid=tmpid/16;

        switch (ttmpig)

        {

            case 10:

                nLetterValue =@"A";break;

            case 11:

                nLetterValue =@"B";break;

            case 12:

                nLetterValue =@"C";break;

            case 13:

                nLetterValue =@"D";break;

            case 14:

                nLetterValue =@"E";break;

            case 15:

                nLetterValue =@"F";break;

            default:nLetterValue=[[NSString alloc]initWithFormat:@"%lli",ttmpig];
}
str = [nLetterValue stringByAppendingString:str]; if (tmpid == 0) { break; }
}
return str;
}

16进制转为NSData

+ (NSData *)convertHexStrToData:(NSString *)str
{
if (!str || [str length] == 0) {
return nil;
} NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:20];
NSRange range;
if ([str length] % 2 == 0) {
range = NSMakeRange(0, 2);
} else {
range = NSMakeRange(0, 1);
}
for (NSInteger i = range.location; i < [str length]; i += 2) {
unsigned int anInt;
NSString *hexCharStr = [str substringWithRange:range];
NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr]; [scanner scanHexInt:&anInt];
NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
[hexData appendData:entity]; range.location += range.length;
range.length = 2;
}
return hexData;
}

结束。谢谢看官!

iOS与硬件通讯(socket,data拼接,发送指令,解析指令)的更多相关文章

  1. [深入浅出Cocoa]iOS网络编程之Socket

    http://blog.csdn.net/kesalin/article/details/8798039 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   [深入浅出Co ...

  2. iOS实现XMPP通讯(二)XMPP编程

    项目概述 这是一个可以登录jabber账号,获取好友列表,并且能与好友进行聊天的项目. 使用的是第三方库XMPPFramework框架来实现XMPP通讯. 项目地址:XMPP-Project 项目准备 ...

  3. HTTP 笔记与总结(3 )socket 编程:发送 GET 请求

    使用 PHP + socket 模拟发送 HTTP GET 请求,过程是: ① 打开连接 ② 构造 GET 请求的数据:写入请求行.请求头信息.请求主体信息(GET 请求没有主体信息) ③ 发送 GE ...

  4. Socket.io各个发送消息的含义【发送对象范围】

    Socket.io各个发送消息的含义   // send to current request socket client socket.emit('message', "this is a ...

  5. iOS开发网络篇—Socket编程

    一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程 ...

  6. iOS 网络编程:socket

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  7. 项目总结22:Java UDP Socket数据的发送和接收

    项目总结22:Java UDP Socket数据的发送和接收 1-先上demo 客户端(发送数据) package com.hs.pretest.udp; import java.io.IOExcep ...

  8. error: 'Can't connect to local MySQL server through socket '/data/3307/data/mysql.sock' (2)'

    centos7.5 重启mysql报错 问题: [root@db01-51 ~]# mysqladmin -uroot -p123 -S /data/3307/data/mysql.sock shut ...

  9. iOS开发过程中使用Core Data应避免的十个错误

    原文出处: informit   译文出处:cocoachina Core Data是苹果针对Mac和iOS平台开发的一个框架,主要用来储存数据.对很多开发者来说,Core Data比较容易入手,但很 ...

随机推荐

  1. LeetCode 544----Output Contest Matches

    During the NBA playoffs, we always arrange the rather strong team to play with the rather weak team, ...

  2. Android 仿美团网,探索使用ViewPager+GridView实现左右滑动查看更多分类的功能

    看下效果图,自己考虑下自己会如何实现,然后再继续看看作者的实现~ 不记得什么时候,我留意到到美团网首页有使用ViewPager+GridView实现左右滑动查看更多分类的一个功能,感觉它很有趣,于是想 ...

  3. 分布式部署下的报表调用 API调用 权限问题以及性能方案

     背景描述: 客户的实际情况是需要在具体系统构架前,通过与厂商讨论确定最终的系统架构方案. 需求是客户自己有管理系统,希望建立一个独立的报表服务器,该报表服务器可以对多个管理系统提供报表服务,不知 ...

  4. ES6-Generator

    Generator 关键词:状态机,遍历器,同步方式写异步方法 基本概念 形式上,Generator函数是一个普通函数,但是有两个特征. function关键字与函数名之间有一个星号. 二是,函数体内 ...

  5. ASP.NET中母版页引用外部js或css文件无效,提示对象未定义解决方法

    最近做网站用了一个js+css实现的带有二级菜单的导航条,在母版页创建好后,子页面调用出现了许多奇怪的问题,多方查证后的最终解决方案和大家分享下.... 1.路径问题 如果是一个单独的aspx页面调用 ...

  6. SQL Server 索引知识-概念

    概念篇 索引概念(index concept) 一种表或视图中相关的B-tree的数据结构.索引键列由一列或多列组成.可拥有包含性列(sql2005).用于提升Sql Server 查找相关数据行效率 ...

  7. ffemp语音转码

    分享一款windows上很不错的  程序员专业转码软件 ffemp 首先先下载ffemp转码软件 https://pan.baidu.com/s/10BoahyWJlI9e-_rB_yCiLA 下载之 ...

  8. Git 如何上传文件夹

    Github开源代码库以及版本控制系统,可以托管各种git库,并提供web访问界面.很多朋友喜欢喜欢将个人Blog或小型项目托管到github,这样既方便又简单. 下面介绍如何将本地文件上传到gith ...

  9. 工作中碰到的一个问题(cookie相关)

    今天上线了一个API,6台机器做的集群.API的第一步是读取cookie,判断用户是否登录. 例如,线上服务器分别是 10.255.242.1 10.255.242.2 10.255.242.3 10 ...

  10. 囧啊!!时间戳转化为时间出错php

    最近写了一个api,测试也没发现啥问题.可是上线之后发现有时api的返回结果不正确.为什么呢? 调我接口的同学给了两个调用示例,理论上两个的结果应该一致,实际结果却不一致. api调用带了一个时间戳参 ...