2023-12-11 13:44:15 +08:00

743 lines
29 KiB
Objective-C
Executable File

//
// udp_data_class.m
// myhome
//
// Created by user on 12-10-31.
// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//
#import "UdpHelper.h"
#import "Sformat.h"
#import "Pub.h"
#import "Msg.h"
@interface UdpHelper (){
}
@end
@implementation UdpHelper{
}
- (void)Open{
_sysinfo = [Pub getApp].sysinfo;
_udp = [[AsyncUdpSocket alloc] initWithDelegate:self];
//NSError *err = nil;
//[_udp bindToPort:8366 error:&err];
[_udp receiveWithTimeout:-1 tag:0];
[self udp_send_thr_begin];
_timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self selector:@selector(HeartBeat)
userInfo:nil repeats:YES];
}
- (void)Resume{
_udp = [[AsyncUdpSocket alloc] initWithDelegate:self];
[_udp receiveWithTimeout:-1 tag:0];
}
- (void)udp_send_thr_begin
{
_udp_datas = [[NSMutableArray alloc] init];
udp_data_class *list;
// _udp_list = [[udp_data_class alloc] init];
for (int i=0; i<BUFNUM; i++) {
list = [[udp_data_class alloc] init];
list.isUsed = FALSE;
[_udp_datas addObject:list];
}
// 没有任何意义 只是为了条件无限循环
_udp_send_tag = YES;
// 记录子线程发送的次数
_udp_send_time = 0;
// 创建一个子线程
[NSThread detachNewThreadSelector:@selector(udp_send_thr) toTarget:self withObject:nil];
}
//upd 线程
- (void)udp_send_thr{
while(_udp_send_tag){
// 如果线程发送的次数小于等于0 不发送等待
while (_udp_send_time <= 0) {
@try
{
[_udp_send_Condition wait];
sleep(1);
}
@catch (NSException * e) {
}
//[NSThread sleepForTimeInterval:0.01];
//NSLog(@"线程等待");
}
[_udp_send_Condition lock];
//事件
// 有事件发送
BOOL hasDataSend = YES;
while (hasDataSend) {
@try
{
// 如果有事件发送 立马改变状态
hasDataSend = FALSE;
// 遍历子线程 创建的队列里面的对象
for(int i=0; i<BUFNUM; i++) {
// 取到创建的队列里面的对象
_udp_list = [_udp_datas objectAtIndex:i];
//NSLog(@"send to i=%d, port = %d, _udp_datas.count = %lu", i, _udp_list.port, (unsigned long)_udp_datas.count);
// isUsed为yes 说明有向服务器发送数据
if (_udp_list.isUsed) {
NSLog(@"hasDataSend:i=%d", i);
//发送时间超时判断
if(_udp_list.sendtimes < _udp_list.sendtimesneed) {
hasDataSend = YES;
_udp_list.sendtimes ++;
[_udp_datas replaceObjectAtIndex:i withObject:_udp_list];
[self performSelectorOnMainThread:@selector(sendDataInMain) withObject:nil waitUntilDone:YES];
}
else { //发送数据到服务器,超时 处理 无法连接
_udp_list.sendtimes = 0;
_udp_list.isUsed = FALSE;
[_udp_datas replaceObjectAtIndex:i withObject:_udp_list];
Byte *bb = (Byte *)[_udp_list.data bytes];
switch (bb[6]) {
case 150:{//通话
if(bb[8]==1) {
}
else if(bb[8]==10) {
NSLog(@"开锁失败");
[[Pub getApp] OpenDoorFail:[Pub getEquidFrombb:bb at:9]];
}
else if(bb[8]==30) {
NSLog(@"停止通话失败");
//[talk_class status_ini_onMain];
}
}
break;
case 152: {//监视
if(bb[8]==1) {
NSLog(@"监视失败");
if([Pub getApp].callOut){
dispatch_async(dispatch_get_main_queue(), ^{//转到主线程处理
[[Pub getApp].callOut UIClose];
});
}
else{
//在主页开锁
[[Pub getApp] OpenDoorFail:[Pub getEquidFrombb:bb at:9]];
}
}
else if(bb[8]==10) {
NSLog(@"开锁失败");
[[Pub getApp] playSoundWith:SoundError];
[[Pub getApp] OpenDoorFail:[Pub getEquidFrombb:bb at:9]];
}
else if(bb[8]==30) {
NSLog(@"停止监视失败");
//[talk_class status_ini_onMain];
}
}
break;
default:
break;
}
}
}
else{
}
}
sleep(1);
} @catch (NSException * e) {
}
}
//[self performSelectorOnMainThread:@selector(refData) withObject:nil waitUntilDone:YES];
//事件完
_udp_send_time--;
[_udp_send_Condition unlock];
}
}
- (void)HeartBeat{
//NSLog(@"HeartBeat");
if ((YES == [_udp isClosed]) ) {
_udp = [[AsyncUdpSocket alloc] initWithDelegate:self];
//NSError *err = nil;
//[_udp bindToPort:8366 error:&err];
[_udp receiveWithTimeout:-1 tag:0];
}
@try
{
if (![_sysinfo.username isEqualToString:@""]) {
if ([_sysinfo.token isEqualToString:@""]) return;
//NSLog(@"%d,%ld,%d",_online,([Sformat timestamp]-_udp_last_report_time)/1000,sysinfo.reporttime);
if (_online==NO || (([Sformat timestamp]-_udp_last_report_time)/1000 > _sysinfo.reporttime)) {//心跳包时间 如果没有收到_udp回应 则继续发
_udp_last_report_time = [Sformat timestamp];
Byte bb[110];
/*
memset(bb, 0, 101);
[Pub addHead:@"XXXCID" toByte:bb];
bb[6] = 4;
bb[7] = 1;
[Pub addEquid:@"P18682150237" toByte:bb at:8];
// [Pub addEquid:_sysinfo.equid toByte:bb at:8];
bb[20] = 0;
[Pub addMac:[Pub getMac] toByte:bb at:28];
[Pub addInt:0 toByte:bb at:34];
[Pub addEquid:[Pub getLocalIP] toByte:bb at:38];
//与协议区别
[Pub addGKB:@"token" toByte:bb at:50];
int len = [Pub addGKB:_sysinfo.token toByte:bb at:60];
[Pub addInt:len toByte:bb at:43];
NSData *data = [[NSData alloc] initWithBytes:bb length:60+len];
//NSLog(@"HeartBeat: length = %ld , %@", data.length, [Sformat Hex:data]);
self.sysinfo.server_wan = @"192.168.254.23";//测试葛工地址
self.sysinfo.server_port = 8366;
NSLog(@"HeartBeat: 服务器=%@:%d; 本地端口 = %d ",self.sysinfo.server_wan,self.sysinfo.server_port, _udp.localPort);]
*/
memset(bb, 0, 101);
[Pub addHead:@"XXXCID" toByte:bb];
bb[6] = 4;
bb[7] = 1;
[Pub addEquid:@"P18682150237" toByte:bb at:8];
// [Pub addEquid:_sysinfo.equid toByte:bb at:8];
bb[20] = 0;
[Pub addMac:@"02:00:00:00:00:00" toByte:bb at:28];
// [Pub addMac:[Pub getMac] toByte:bb at:28];
[Pub addInt:0 toByte:bb at:34];
[Pub addEquid:@"192.168.9.7" toByte:bb at:38];
// [Pub addEquid:[Pub getLocalIP] toByte:bb at:38];
//与协议区别
[Pub addGKB:@"token" toByte:bb at:50];
int len = [Pub addGKB:@"b989fa15f75c2ac02718b7c9bb64f80e" toByte:bb at:60];
// int len = [Pub addGKB:_sysinfo.token toByte:bb at:60];
[Pub addInt:len toByte:bb at:43];
NSData *data = [[NSData alloc] initWithBytes:bb length:60+len];
//打印数据
NSMutableString *str = [[NSMutableString alloc] init];
for (int i = 0; i < sizeof(bb); i++) {
[str appendFormat:@"%@", [NSString stringWithFormat:@"%d ", bb[i]]];
}
NSLog(@"\n%@", str);
/*
storeDataInByteArray(bb, @"XXXCID", 0);//包头
storeDataInByteArray(bb, @(4), 6);//命令4
storeDataInByteArray(bb, @(1), 7);//命令类型1
storeDataInByteArray(bb, @"P18682150237", 8);//用户名
storeDataInByteArray(bb, @(0), 20);
storeDataInByteArray(bb, @(0), 28);//Mac地址
storeDataInByteArray(bb, @"0.0.0.0", 38);//IP地址
storeDataInByteArray(bb, @"token", 50);//Token
storeDataInByteArray(bb, @"34237b42ae0ef7eb8fa6c1adf3ccfabb", 60);//Token值
storeDataInByteArray(bb, @(32), 43);//Token值length
NSMutableString *str = [[NSMutableString alloc] init];
for (int i = 0; i < sizeof(bb); i++) {
[str appendFormat:@"%@", [NSString stringWithFormat:@"%d ", bb[i]]];
}
NSLog(@"\n%@", str);
NSData *data = [[NSData alloc] initWithBytes:bb length:60+32];
*/
[_udp sendData:data toHost:@"192.168.254.23" port:8366 withTimeout:-1 tag:0];
// if([Pub getApp].p2ptest){
// [_udp sendData:data toHost:@"47.107.109.110" port:self.sysinfo.server_port withTimeout:-1 tag:0];
// }
//[_udp sendData:data toHost:self.sysinfo.server_wan port:self.sysinfo.server_port withTimeout:-1 tag:0];
}
if (_online == YES && ([Sformat timestamp] - _udp_last_replay_time )/1000 > 3*_sysinfo.reporttime) {
//[Msg alert:@"离线"];
_online = NO;
}
}
} @catch (NSException * ex) {
NSLog(@"心跳包错误");
}
}
void storeDataInByteArray(Byte a[], id data, NSUInteger index) {
// if (index >= sizeof(a)) {
// NSLog(@"索引超出数组容量。");
// return;
// }
if ([data isKindOfClass:[NSString class]]) {
NSString *stringValue = (NSString *)data;
const char *utf8String = [stringValue UTF8String];
NSUInteger stringLength = [stringValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
memcpy(a + index, utf8String, stringLength);
} else if ([data isKindOfClass:[NSNumber class]]) {
NSNumber *numberValue = (NSNumber *)data;
a[index] = [numberValue unsignedCharValue];
} else {
NSLog(@"不支持的数据类型。");
}
}
- (BOOL)sendDataInMain
{
//BOOL res =
NSLog(@"sendDataInMain remoteip=%@;port=%d",_udp_list.toHost,_udp_list.port);
//NSLog(@"sendDataInMain %@",[Sformat Hex:_udp_list.data]);
//NSLog(@"sendDataInMain: 本地端口 = %d ", _udp.localPort);
[_udp sendData:_udp_list.data
toHost:_udp_list.toHost
port:_udp_list.port
withTimeout:-1
tag:0];
//NSLog(@"数据长度:%lu",(unsigned long)_udp_list.data.length);
//NSLog(@"%@:%d", _udp_list.toHost, _udp_list.port);
return YES;
}
- (void)senddataInThr:(NSData *)data toHost:(NSString *)host toPort:(int)port at:(int)second setTag:(int)tag
{
for (int i=0; i<BUFNUM; i++) {
udp_data_class *list = [_udp_datas objectAtIndex:i];
if (!list.isUsed) {
NSLog(@"i=%d",i);
list.isUsed = YES;
list.sendtimes = 0;
list.sendtimesneed = second;
list.data = data;
list.toHost = host;
list.port = port;
//list.byport = port;
list.tag = tag;
break;
}
}
NSLog(@"time=%d", _udp_send_time);
//if (udp_send_time<=0) {
[_udp_send_Condition lock];
_udp_send_time++;
[_udp_send_Condition signal];
[_udp_send_Condition unlock];
//}
}
- (void)sendDataInMain:(Byte *)rr length:(int)len toHost:(NSString *)host toPort:(int)port
{
NSData *data = [[NSData alloc] initWithBytes:rr length:len];
NSArray *aa = [[NSArray alloc] initWithObjects:data, host, [[NSString alloc] initWithFormat:@"%d", port], nil];
//[self performSelectorOnMainThread:@selector(sendDataInMain:) withObject:aa waitUntilDone:YES];
dispatch_async(dispatch_get_main_queue(), ^{//转到主线程处理
//NSLog(@"8302--%lu,%@:%d",(unsigned long)data.length,host,port);
[_udp sendData:data
toHost:host
port:port
withTimeout:-1
tag:0];
});
}
- (void)sendDataInMain:(NSArray *)a
{
NSData *data = (NSData *)[a objectAtIndex:0];
NSString *host = (NSString *)[a objectAtIndex:1];
int port = [(NSString *)[a objectAtIndex:2] intValue];
//NSLog(@"8302--%lu,%@:%d",(unsigned long)data.length,host,port);
[_udp sendData:data
toHost:host
port:port
withTimeout:-1
tag:0];
}
//收到推送接听对讲页面
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock
didReceiveData:(NSData *)data
withTag:(long)tag
fromHost:(NSString *)host
port:(UInt16)port
{
@try{
Byte *bb = (Byte *)[data bytes];
NSData *data1 = [[NSData alloc] initWithBytes:bb length:60+32];
data = data1;
if(data.length==1){
if(bb[0]==0x30||bb[0]==0x31){
NSLog(@"p2p打洞");
if([Pub getApp].p2ptest)
[[Pub getApp].p2ptest GotDadong:bb Len:data.length Formip:host fromport:port];
}
[_udp receiveWithTimeout:-1 tag:0];
return YES;
}
if (bb[6] == 4) {
if(bb[7]==2){
NSLog(@"心跳包反馈");
//[[Pub getApp] playSoundWith:SoundOK];
//if(_online == NO)[Msg alert:@"上线"];
_online = YES;
_udp_last_replay_time = [Sformat timestamp];
}
else if(bb[7]==3){
[Msg alert:@"您已在其他设备登录"];
//warnning
// dispatch_async(dispatch_get_main_queue(), ^{//转到主线程处理
// //[Msg Alert:self Msg:ret];
// [[Pub getApp] LogOut];
// [Pub getApp].login = [[Login alloc] initWithNibName:@"Login" bundle:nil];
// [Pub getApp].main = nil;
// [Pub getApp].window.rootViewController = [Pub getApp].login ;
// [[Pub getApp].window makeKeyAndVisible];
// });
}
}
else if (bb[6] == 150) {
// if( [Pub getApp].main == nil ){
// [_udp receiveWithTimeout:-1 tag:0];
// return YES;
// }
if( [Pub getApp].isBack){
[_udp receiveWithTimeout:-1 tag:0];
return YES;
}
//[[Pub getApp].main alert:@"呼叫"];
if([Sformat timestamp] - [Pub getApp].sysinfo.launchtime < 2000 ){
[_udp receiveWithTimeout:-1 tag:0];
return YES;
}
//NSLog(@"对讲命令:%d",bb[6]&0xff);
switch (bb[8]&0xff) {
NSLog(@"被呼叫2");
case 1:
//被叫
[[Pub getApp].talk BeCall:bb Len:data.length Formip:host fromport:port];
break;
case 6:{//接听
if((bb[7]&0x3)==2){//被叫 接听反馈
NSLog(@"接听反馈");
[self stopSend:@"" rr6:150 rr8:6];
[[Pub getApp].talk talkOnRec:bb];
}
}
break;
case 7:
case 8:{//音视频数据
//NSLog(@"音视频数据");
[[Pub getApp].talk getAVData:bb withLength:data.length];
}
break;
case 9:{//保持连接
if((bb[7]&0x3)==1){//对方保持连接
//NSLog(@"对方保持连接");
bb[7] = 2;
[[Pub getApp].udp.udp sendData:[[NSData alloc] initWithBytes:bb length:100]
toHost:host
port:port
withTimeout:-1
tag:0];
[Pub getApp].talk.connect_reg_time = [Sformat timestamp];
}
else{
//NSLog(@"保持连接反馈");
[Pub getApp].talk.connect_reg_time = [Sformat timestamp];
}
}
break;
case 10:{//开门反馈
if((bb[7]&0x3)==2){
NSLog(@"开门成功");
if([self stopSend:@"" rr6:150 rr8:10]>-1){
[[Pub getApp] OpenDoorSucc:[Pub getEquidFrombb:bb at:9]];
}
}
else{
if([self stopSend:@"" rr6:150 rr8:10]>-1){
[[Pub getApp] OpenDoorFail:[Pub getEquidFrombb:bb at:9]];
}
}
}
break;
case 30:{//对讲结束
if((bb[7]&0x3)==1){//对方结束对讲
NSLog(@"对方结束对讲");
bb[7] = 2;
[[Pub getApp].udp.udp sendData:[[NSData alloc] initWithBytes:bb length:100]
toHost:host
port:port
withTimeout:-1
tag:0];
[[Pub getApp].talk status_ini];
if([Pub getApp].callOut){
[[Pub getApp].callOut UIClose];
}
}
else{//结束对讲反馈
NSLog(@"结束对讲反馈");
[self stopSend:@"" rr6:150 rr8:30];
}
}
break;
case 140:{//p2p测试
if([Pub getApp].p2ptest)
[[Pub getApp].p2ptest GotMyPortInServer:bb Len:data.length Formip:host fromport:port];
}
break;
case 141:{//p2p测试
if([Pub getApp].p2ptest)
[[Pub getApp].p2ptest GotRemoteIp:bb Len:data.length Formip:host fromport:port];
}
break;
case 142:{//p2p测试
NSLog(@"p2p被叫");
if([Pub getApp].p2ptest)
[[Pub getApp].p2ptest GotCall:bb Len:data.length Formip:host fromport:port];
}
break;
case 144:
case 143:{//p2p测试 NSAsk
NSLog(@"p2pNSAskNSAsk");
if([Pub getApp].p2ptest)
[[Pub getApp].p2ptest GotNSAsk:bb Len:data.length Formip:host fromport:port];
}
break;
default:
break;
}
}
else if(bb[6] == 152){
switch (bb[8]&0xff) {
case 2://被叫
NSLog(@"对方忙");
[self stopSend:@"" rr6:152 rr8:1];
if([Pub getApp].callOut){
[[Pub getApp].callOut UIClose];
}
break;
case 4:{//监视成功
NSLog(@"监视成功");
[self stopSend:@"" rr6:152 rr8:1];
if([Pub getApp].callOut){
[[Pub getApp].talk watchSucc:bb Len:data.length Formip:host fromport:port];
}
else if([Pub getApp].main){
// [[Pub getApp].main OpendoorGo];
[[Pub getApp].main OpenDoorStep2];
}
}
break;
case 7:
case 8:{//音视频数据
//NSLog(@"音视频数据");
[[Pub getApp].talk getAVData:bb withLength:data.length];
}
break;
case 9:{//保持连接
if((bb[7]&0x3)==1){//对方保持连接
//NSLog(@"对方保持连接");
bb[7] = 2;
[[Pub getApp].udp.udp sendData:[[NSData alloc] initWithBytes:bb length:100]
toHost:host
port:port
withTimeout:-1
tag:0];
[Pub getApp].talk.connect_reg_time = [Sformat timestamp];
}else{
//NSLog(@"保持连接反馈");
[Pub getApp].talk.connect_reg_time = [Sformat timestamp];
}
}
break;
case 10:{//开门反馈
if((bb[7]&0x3)==2){
NSLog(@"开门成功");
if([self stopSend:@"" rr6:152 rr8:10]>-1){
[[Pub getApp] OpenDoorSucc:[Pub getEquidFrombb:bb at:9]];
}
}else{
if([self stopSend:@"" rr6:152 rr8:10]>-1){
[[Pub getApp] OpenDoorFail:[Pub getEquidFrombb:bb at:9]];
}
}
}
break;
case 30:{//监视结束
if((bb[7]&0x3)==1){//对方结束监视
NSLog(@"对方结束监视");
bb[7] = 2;
[[Pub getApp].udp.udp sendData:[[NSData alloc] initWithBytes:bb length:100]
toHost:host
port:port
withTimeout:-1
tag:0];
[[Pub getApp].talk status_ini];
if([Pub getApp].callOut){
[[Pub getApp].callOut UIClose];
}
}
else{//结束监视反馈
NSLog(@"结束监视反馈");
[self stopSend:@"" rr6:150 rr8:30];
}
}
break;
default:
break;
}
}
} @catch (NSException * ex) {
NSLog(@"心跳包错误");
}
[_udp receiveWithTimeout:-1 tag:0];
return YES;
}
- (int)stopSend:(NSString *)host rr6:(int)r6 rr8:(int)r8
{
for (int i=0; i<BUFNUM; i++) {
udp_data_class *list = [[udp_data_class alloc] init];
list = [_udp_datas objectAtIndex:i];
if (list.isUsed) {
if( ([host isEqualToString:@""])|([list.toHost isEqualToString:host])) {
Byte *bb=(Byte *)[list.data bytes];
if (r8 == -1) {
if (bb[6]==r6) {
NSLog(@"clear");
list.isUsed = FALSE;
[_udp_datas replaceObjectAtIndex:i withObject:list];
return i;
}
}
else {
if ((bb[6]==r6)&(bb[8]==r8)) {
NSLog(@"clear");
list.isUsed = FALSE;
[_udp_datas replaceObjectAtIndex:i withObject:list];
return i;
}
}
}
}
else {
}
}
return -1;
}
- (int)ChgSendIp:(NSString *)host rr6:(int)r6 rr8:(int)r8 Port:(int)port
{
for (int i=0; i<BUFNUM; i++) {
udp_data_class *list = [[udp_data_class alloc] init];
list = [_udp_datas objectAtIndex:i];
if (list.isUsed) {
Byte *bb=(Byte *)[list.data bytes];
if ((bb[6]==r6)&(bb[8]==r8)) {
list.toHost = host;
list.port = port;
[_udp_datas replaceObjectAtIndex:i withObject:list];
return i;
}
}
}
return -1;
}
- (int)stopSendDadong
{
for (int i=0; i<BUFNUM; i++) {
udp_data_class *list = [[udp_data_class alloc] init];
list = [_udp_datas objectAtIndex:i];
if (list.isUsed) {
Byte *bb=(Byte *)[list.data bytes];
if (list.data.length==1) {
list.isUsed = FALSE;
[_udp_datas replaceObjectAtIndex:i withObject:list];
return i;
}
}
}
return -1;
}
- (int)stopSend:(NSString *)host rr6:(int)r6 rr8:(int)r8 Port:(int)port
{
for (int i=0; i<BUFNUM; i++) {
udp_data_class *list = [[udp_data_class alloc] init];
list = [_udp_datas objectAtIndex:i];
if (list.isUsed) {
if(list.port !=port)continue;
if( ([host isEqualToString:@""])|([list.toHost isEqualToString:host])) {
Byte *bb=(Byte *)[list.data bytes];
if (r8 == -1) {
if (bb[6]==r6) {
NSLog(@"clear");
list.isUsed = FALSE;
[_udp_datas replaceObjectAtIndex:i withObject:list];
return i;
}
}
else {
if ((bb[6]==r6)&(bb[8]==r8)) {
NSLog(@"clear");
list.isUsed = FALSE;
[_udp_datas replaceObjectAtIndex:i withObject:list];
return i;
}
}
}
}
else {
}
}
return -1;
}
@end