// ///////////////////////////////////////////////////////////////////////////////
// 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
(0,
[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