Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 804 → Rev 805

/iKopter/trunk/Classes/Communication/MKConnectionController.m
0,0 → 1,414
// ///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2010, Frank Blumenberg
//
// See License.txt for complete licensing and attribution information.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// ///////////////////////////////////////////////////////////////////////////////
 
#import "SynthesizeSingleton.h"
#import "MKConnectionController.h"
#import "NSData+MKCommandDecode.h"
#import "NSData+MKCommandEncode.h"
#import "NSData+MKPayloadDecode.h"
#import "MKDataConstants.h"
#import "MKHost.h"
#import "MKIpConnection.h"
 
// ///////////////////////////////////////////////////////////////////////////////
 
NSString * const MKConnectedNotification = @"MKConnectedNotification";
NSString * const MKDisconnectedNotification = @"MKDisconnectedNotification";
NSString * const MKDisconnectErrorNotification = @"MKDisconnectErrorNotification";
 
NSString * const MKVersionNotification = @"MKVersionNotification";
NSString * const MKDebugDataNotification = @"MKDebugDataNotification";
NSString * const MKDebugLabelNotification = @"MKDebugLabelNotification";
NSString * const MKLcdMenuNotification = @"MKLcdMenuNotification";
NSString * const MKLcdNotification = @"MKLcdNotification";
NSString * const MKReadSettingNotification = @"MKReadSettingNotification";
NSString * const MKWriteSettingNotification = @"MKWriteSettingNotification";
NSString * const MKChangeSettingNotification = @"MKChangeSettingNotification";
 
NSString * const MKChannelValuesNotification = @"MKChannelValuesNotification";
 
NSString * const MKReadMixerNotification = @"MKReadMixerNotification";
NSString * const MKWriteMixerNotification = @"MKWriteMixerNotification";
 
NSString * const MKOsdNotification = @"MKOsdNotification";
 
// ///////////////////////////////////////////////////////////////////////////////
 
@implementation MKConnectionController
 
// -------------------------------------------------------------------------------
 
//@synthesize hostOrDevice;
//@synthesize inputController;
 
@synthesize primaryDevice;
@synthesize currentDevice;
 
-(void) setCurrentDevice:(MKAddress)theAddress {
// if(primaryDevice==MKAddressNC) {
if(theAddress != currentDevice) {
currentDevice=theAddress;
if(currentDevice==MKAddressNC)
{
uint8_t bytes[5];
bytes[0] = 0x1B;
bytes[1] = 0x1B;
bytes[2] = 0x55;
bytes[3] = 0xAA;
bytes[4] = 0x00;
bytes[5] = '\r';
NSData * data = [NSData dataWithBytes:&bytes length:6];
[self sendRequest:data];
}
else {
uint8_t byte=0;
 
switch (currentDevice) {
case MKAddressFC:
byte=0;
break;
case MKAddressMK3MAg:
byte=1;
break;
}
 
NSData * data = [NSData dataWithCommand:MKCommandRedirectRequest
forAddress:MKAddressNC
payloadForByte:byte];
[self sendRequest:data];
}
}
// }
}
 
 
SYNTHESIZE_SINGLETON_FOR_CLASS(MKConnectionController);
 
// -------------------------------------------------------------------------------
 
- (void) dealloc {
[hostOrDevice release];
[inputController release];
[shortVersions[MKAddressFC] release];
[shortVersions[MKAddressNC] release];
[shortVersions[MKAddressMK3MAg] release];
[longVersions[MKAddressMK3MAg] release];
[longVersions[MKAddressNC] release];
[longVersions[MKAddressMK3MAg] release];
[super dealloc];
}
 
// -------------------------------------------------------------------------------
 
- (void) start:(MKHost*)host {
if (![inputController isConnected]) {
Class nsclass = NSClassFromString(host.connectionClass);
if (!nsclass) {
nsclass = [MKIpConnection class];
}
[inputController release];
inputController = [[nsclass alloc] initWithDelegate:self];
 
[hostOrDevice release];
hostOrDevice = [NSString stringWithFormat:@"%@:%d",host.address,host.port];
[hostOrDevice retain];
didPostConnectNotification = NO;
currentDevice=MKAddressAll;
primaryDevice=MKAddressAll;
NSError * err = nil;
if (![inputController connectTo:hostOrDevice error:&err]) {
NSLog(@"Error: %@", err);
}
}
}
 
- (void) stop {
if ([inputController isConnected]) {
DLog(@"disconnect");
[inputController disconnect];
}
// self.inputController=nil;
 
}
 
- (BOOL) isRunning;
{
return [inputController isConnected];
}
 
- (void) sendRequest:(NSData *)data;
{
DLog(@"%@",data);
NSString * msg = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
DLog(@"%@", msg);
 
[inputController writeMkData:data];
}
 
- (NSString *) shortVersionForAddress:(MKAddress)theAddress;
{
if (theAddress <= MKAddressAll || theAddress > MKAddressMK3MAg)
return nil;
return shortVersions[theAddress];
}
 
- (NSString *) longVersionForAddress:(MKAddress)theAddress;
{
if (theAddress <= MKAddressAll || theAddress > MKAddressMK3MAg)
return nil;
return longVersions[theAddress];
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
 
///////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL) hasNaviCtrl {
return primaryDevice==MKAddressNC;
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void) activateNaviCtrl {
if(primaryDevice!=MKAddressAll && ![self hasNaviCtrl])
return;
uint8_t bytes[5];
bytes[0] = 0x1B;
bytes[1] = 0x1B;
bytes[2] = 0x55;
bytes[3] = 0xAA;
bytes[4] = 0x00;
bytes[5] = '\r';
NSData * data = [NSData dataWithBytes:&bytes length:6];
[self sendRequest:data];
currentDevice=MKAddressNC;
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void) activateFlightCtrl {
 
if(![self hasNaviCtrl])
return;
 
uint8_t byte=0;
NSData * data = [NSData dataWithCommand:MKCommandRedirectRequest
forAddress:MKAddressNC
payloadForByte:byte];
[self sendRequest:data];
currentDevice=MKAddressFC;
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void) activateMK3MAG {
 
if(![self hasNaviCtrl])
return;
 
uint8_t byte=1;
NSData * data = [NSData dataWithCommand:MKCommandRedirectRequest
forAddress:MKAddressNC
payloadForByte:byte];
[self sendRequest:data];
currentDevice=MKAddressMK3MAg;
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void) activateMKGPS {
 
if(![self hasNaviCtrl])
return;
 
uint8_t byte=3;
NSData * data = [NSData dataWithCommand:MKCommandRedirectRequest
forAddress:MKAddressNC
payloadForByte:byte];
[self sendRequest:data];
currentDevice=MKAddressMKGPS;
}
 
 
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark MKInputDelegate
 
 
- (void) requestPrimaryDeviceVersion {
NSData * data = [NSData dataWithCommand:MKCommandVersionRequest
forAddress:MKAddressAll
payloadWithBytes:NULL
length:0];
[self sendRequest:data];
}
 
- (void) didConnectTo:(NSString *)hostOrDevice {
[self activateNaviCtrl];
[self performSelector:@selector(requestPrimaryDeviceVersion) withObject:self afterDelay:0.1];
}
 
- (void) willDisconnectWithError:(NSError *)err {
NSDictionary * d = [NSDictionary dictionaryWithObjectsAndKeys:err, @"error", nil];
 
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
 
[nc postNotificationName:MKDisconnectErrorNotification object:self userInfo:d];
}
 
- (void) didDisconnect {
NSDictionary * d = nil;
 
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
 
[nc postNotificationName:MKDisconnectedNotification object:self userInfo:d];
 
}
 
- (void) setVersionsFrom:(NSDictionary *)d forAddress:(MKAddress)address {
if (address != MKAddressAll) {
[shortVersions[address] release];
shortVersions[address] = [[d objectForKey:kMKDataKeyVersion] retain];
[longVersions[address] release];
longVersions[address] = [[d objectForKey:kMKDataKeyVersionShort] retain];
}
}
 
- (void) didReadMkData:(NSData *)data {
NSData * strData = [data subdataWithRange:NSMakeRange(1, [data length] - 1)];
 
NSString * msg = [[[NSString alloc] initWithData:strData encoding:NSASCIIStringEncoding] autorelease];
DLog(@">>%@<<", msg);
if ([strData isCrcOk]) {
// DLog(@"Data length %d",[strData length]);
 
NSData * payload = [strData payload];
MKAddress address = [strData address];
NSDictionary * d = nil;
NSString * n = nil;
 
switch ([strData command]) {
case MKCommandLcdMenuResponse:
n = MKLcdMenuNotification;
d = [payload decodeLcdMenuResponseForAddress:address];
break;
case MKCommandLcdResponse:
n = MKLcdNotification;
d = [payload decodeLcdResponseForAddress:address];
break;
case MKCommandDebugLabelResponse:
n = MKDebugLabelNotification;
d = [payload decodeAnalogLabelResponseForAddress:address];
break;
case MKCommandDebugValueResponse:
n = MKDebugDataNotification;
d = [payload decodeDebugDataResponseForAddress:address];
break;
case MKCommandChannelsValueResponse:
n = MKChannelValuesNotification;
d = [payload decodeChannelsDataResponse];
break;
case MKCommandReadSettingsResponse:
n = MKReadSettingNotification;
d = [payload decodeReadSettingResponse];
break;
case MKCommandWriteSettingsResponse:
n = MKWriteSettingNotification;
d = [payload decodeWriteSettingResponse];
break;
case MKCommandMixerReadResponse:
n = MKReadMixerNotification;
d = [payload decodeMixerReadResponse];
break;
case MKCommandMixerWriteResponse:
n = MKWriteMixerNotification;
d = [payload decodeMixerWriteResponse];
break;
 
case MKCommandChangeSettingsResponse:
n = MKChangeSettingNotification;
d = [payload decodeChangeSettingResponse];
break;
case MKCommandOsdResponse:
n = MKOsdNotification;
d = [payload decodeOsdResponse];
break;
case MKCommandVersionResponse:
n = MKVersionNotification;
d = [payload decodeVersionResponseForAddress:address];
[self setVersionsFrom:d forAddress:address];
if (!didPostConnectNotification) {
 
currentDevice=address;
primaryDevice=address;
DLog(@"Connected to primaryDevice %d, currentDevice %d",primaryDevice,currentDevice);
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:MKConnectedNotification object:self userInfo:nil];
}
break;
default:
break;
}
if (d)
DLog(@"(%d) %@", [d retainCount],d );
 
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:n object:self userInfo:d];
// if (d)
// DLog(@"(%d)", [d retainCount] );
 
} else {
NSString * msg = [[[NSString alloc] initWithData:strData encoding:NSASCIIStringEncoding] autorelease];
DLog(@"%@", msg);
}
}
 
@end