Skip to content

Commit f10f585

Browse files
author
Larry Tin
committed
Add GDCFirebaseChannel
1 parent 25aac50 commit f10f585

9 files changed

Lines changed: 233 additions & 13 deletions

File tree

Example/GDChannel.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
3F85BD61B5D0E2D0539D9F1A /* libPods-GDChannel.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F004427CEBD8F8E6C19B36D /* libPods-GDChannel.a */; };
11+
46BDF7DE1EF2BE960032D0A8 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 46BDF7DD1EF2BE960032D0A8 /* GoogleService-Info.plist */; };
1112
6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
1213
6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
1314
6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
@@ -22,6 +23,7 @@
2223

2324
/* Begin PBXFileReference section */
2425
2F004427CEBD8F8E6C19B36D /* libPods-GDChannel.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-GDChannel.a"; sourceTree = BUILT_PRODUCTS_DIR; };
26+
46BDF7DD1EF2BE960032D0A8 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
2527
6003F58A195388D20070C39A /* GDChannel.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GDChannel.app; sourceTree = BUILT_PRODUCTS_DIR; };
2628
6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
2729
6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@@ -65,11 +67,28 @@
6567
/* End PBXFrameworksBuildPhase section */
6668

6769
/* Begin PBXGroup section */
70+
46BDF7DB1EF2BE960032D0A8 /* Resources */ = {
71+
isa = PBXGroup;
72+
children = (
73+
46BDF7DC1EF2BE960032D0A8 /* Firebase */,
74+
);
75+
path = Resources;
76+
sourceTree = "<group>";
77+
};
78+
46BDF7DC1EF2BE960032D0A8 /* Firebase */ = {
79+
isa = PBXGroup;
80+
children = (
81+
46BDF7DD1EF2BE960032D0A8 /* GoogleService-Info.plist */,
82+
);
83+
path = Firebase;
84+
sourceTree = "<group>";
85+
};
6886
6003F581195388D10070C39A = {
6987
isa = PBXGroup;
7088
children = (
7189
60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
7290
6003F593195388D20070C39A /* GDChannel */,
91+
46BDF7DB1EF2BE960032D0A8 /* Resources */,
7392
6003F5B5195388D20070C39A /* Tests */,
7493
6003F58C195388D20070C39A /* Frameworks */,
7594
6003F58B195388D20070C39A /* Products */,
@@ -227,6 +246,7 @@
227246
files = (
228247
6003F5A4195388D20070C39A /* Main_iPad.storyboard in Resources */,
229248
6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
249+
46BDF7DE1EF2BE960032D0A8 /* GoogleService-Info.plist in Resources */,
230250
6003F5A1195388D20070C39A /* Main_iPhone.storyboard in Resources */,
231251
6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
232252
);

Example/GDChannel/GDCAppDelegate.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
//
88

99
#import "GDCAppDelegate.h"
10+
#import "Firebase.h"
11+
#import "GDCFirebaseChannel.h"
1012

11-
@implementation GDCAppDelegate
13+
@implementation GDCAppDelegate {
14+
GDCFirebaseChannel *_bus;
15+
}
1216

1317
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1418
{
1519
// Override point for customization after application launch.
20+
[FIRApp configure];
21+
_bus = [[GDCFirebaseChannel alloc] initWithClientId:@"/topics/qq3175830003"];
1622
return YES;
1723
}
1824

Example/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
source 'https://github.com/CocoaPods/Specs.git'
22

33
target 'GDChannel' do
4-
pod "GDChannel", :path => "../"
4+
pod "GDChannel/Firebase", :path => "../"
55
end
66

77
# target 'Tests', :exclusive => true do

Example/Podfile.lock

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,50 @@
11
PODS:
2-
- GDChannel (0.6.0):
2+
- Firebase/Core (4.0.0):
3+
- FirebaseAnalytics (= 4.0.0)
4+
- FirebaseCore (= 4.0.0)
5+
- Firebase/Database (4.0.0):
6+
- Firebase/Core
7+
- FirebaseDatabase (= 4.0.0)
8+
- FirebaseAnalytics (4.0.0):
9+
- FirebaseCore (~> 4.0)
10+
- FirebaseInstanceID (~> 2.0)
11+
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
12+
- FirebaseCore (4.0.0):
13+
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
14+
- FirebaseDatabase (4.0.0):
15+
- FirebaseAnalytics (~> 4.0)
16+
- FirebaseInstanceID (2.0.0):
17+
- FirebaseCore (~> 4.0)
18+
- GDChannel/Core (0.6.0):
319
- MQTTKit (~> 0.1.0)
420
- Protobuf (~> 3.0)
21+
- GDChannel/Firebase (0.6.0):
22+
- Firebase/Database
23+
- GDChannel/Core
24+
- GoogleToolboxForMac/Defines (2.1.1)
25+
- GoogleToolboxForMac/NSData+zlib (2.1.1):
26+
- GoogleToolboxForMac/Defines (= 2.1.1)
527
- MQTTKit (0.1.0)
628
- Protobuf (3.3.0)
729

830
DEPENDENCIES:
9-
- GDChannel (from `../`)
31+
- GDChannel/Firebase (from `../`)
1032

1133
EXTERNAL SOURCES:
1234
GDChannel:
1335
:path: "../"
1436

1537
SPEC CHECKSUMS:
16-
GDChannel: 8fd65c33feff9cb061e85865ce631f3d59267b34
38+
Firebase: 284eea779b73fdff309791817da7c68bff8dd572
39+
FirebaseAnalytics: 6f08e746f7d66f5452931bc2e822b5df9c66b64a
40+
FirebaseCore: 85ad466044c2f013cdb167f85d426d15b128114a
41+
FirebaseDatabase: d829b3a8c3e2ac7a16773c5df226966b0805dfc2
42+
FirebaseInstanceID: 9fbf536668f4d3f0880e7438456dabd1376e294b
43+
GDChannel: 5959aa273e05b71cc52c0c436842e40394083ec1
44+
GoogleToolboxForMac: 8e329f1b599f2512c6b10676d45736bcc2cbbeb0
1745
MQTTKit: a4e6b8aa92db1aeae917d2b773fd72a7749937c4
1846
Protobuf: d582fecf68201eac3d79ed61369ef45734394b9c
1947

20-
PODFILE CHECKSUM: d43afe03f564aee89085e35ebd1c8d15ec07a300
48+
PODFILE CHECKSUM: 8c97f0f6e4a99602e1bb4e93d301a74e7b9ee15d
2149

2250
COCOAPODS: 1.2.0
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>API_KEY</key>
6+
<string>AIzaSyAygC2FFfZ9gpXrMyx5ixEEitq1ptb4Q4w</string>
7+
<key>GCM_SENDER_ID</key>
8+
<string>598242009211</string>
9+
<key>PLIST_VERSION</key>
10+
<string>1</string>
11+
<key>BUNDLE_ID</key>
12+
<string>com.goodow.realtime.GDOperation</string>
13+
<key>GOOGLE_APP_ID</key>
14+
<string>1:598242009211:ios:dbb4c9f3c3d30100</string>
15+
<key>DATABASE_URL</key>
16+
<string>https://tencent-live.firebaseio.com</string>
17+
</dict>
18+
</plist>

GDChannel.podspec

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,23 @@ Pod::Spec.new do |s|
1919
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
2020

2121
s.platform = :ios, '7.0'
22+
s.default_subspec = 'Core'
2223

23-
s.source_files = 'Pod/Classes/**/*', 'Pod/Generated/**/*'
24-
s.requires_arc = ['Pod/Classes/**/*']
24+
s.subspec 'Core' do |sp|
25+
sp.dependency 'MQTTKit', '~> 0.1.0'
26+
sp.dependency 'Protobuf', '~> 3.0'
2527

26-
s.resource_bundle = { 'GDChannel' => 'protos/*.proto' }
28+
sp.source_files = 'Pod/Classes/**/*', 'Pod/Generated/**/*'
29+
sp.requires_arc = ['Pod/Classes/**/*']
30+
sp.exclude_files = 'Pod/Classes/Firebase/**/*'
2731

28-
s.dependency 'MQTTKit', '~> 0.1.0'
29-
s.dependency 'Protobuf', '~> 3.0'
32+
sp.resource_bundle = { 'GDChannel' => 'protos/*.proto' }
33+
end
34+
35+
s.subspec 'Firebase' do |sp|
36+
sp.dependency 'Firebase/Database'
37+
sp.dependency 'GDChannel/Core'
38+
39+
sp.source_files = 'Pod/Classes/Firebase/**/*'
40+
end
3041
end

Pod/Classes/Data/GPBAny+GDChannel.m

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#import "GPBAny+GDChannel.h"
66
#import "GDCSerializable.h"
7+
#import "GPBMessage+JsonFormat.h"
78

89
@implementation GPBAny (GDChannel)
910

@@ -32,10 +33,22 @@ - (__kindof id)unpack {
3233
}
3334

3435
+ (id)packToJson:(id <GDCSerializable>)value {
35-
if (![value isKindOfClass:NSMutableDictionary.class] && ![value isKindOfClass:NSMutableArray.class]) {
36-
NSMutableDictionary *json = value.toJson;
36+
if ([value isKindOfClass:GPBMessage.class]) {
37+
NSMutableDictionary *json = [value toJson];
3738
json[kJsonTypeKey] = [self getTypeUrl:value withPrefix:nil];
3839
return json;
40+
} else if ([value isKindOfClass:NSArray.class]) {
41+
NSMutableArray *array = [NSMutableArray arrayWithCapacity:((NSArray *) value).count];
42+
for (id ele in value) {
43+
if ([ele isKindOfClass:GPBMessage.class]) {
44+
NSMutableDictionary *json = [ele toJson];
45+
json[kJsonTypeKey] = [self getTypeUrl:ele withPrefix:nil];
46+
[array addObject:json];
47+
continue;
48+
}
49+
[array addObject:ele];
50+
}
51+
return array;
3952
}
4053
return value;
4154
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// Created by Larry Tin on 2017/6/11.
3+
//
4+
5+
#import <Foundation/Foundation.h>
6+
7+
@protocol GDCMessage;
8+
9+
@interface GDCFirebaseChannel : NSObject
10+
- (instancetype)initWithClientId:(NSString *)clientId;
11+
12+
- (void)goOnline:(id)clientInfo;
13+
14+
- (void)reportMessage:(id <GDCMessage>)message;
15+
@end
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//
2+
// Created by Larry Tin on 2017/6/11.
3+
//
4+
5+
#import "GDCFirebaseChannel.h"
6+
#import "Firebase.h"
7+
#import "GDCBusProvider.h"
8+
#import "GDCMessageImpl.h"
9+
#import "NSObject+GDChannel.h"
10+
11+
@interface GDCFirebaseChannel ()
12+
@property NSString *clientId;
13+
@property FIRDatabaseReference *bufRef;
14+
@property NSMutableDictionary<NSString *, NSString *> *replyTopics;
15+
@end
16+
17+
@implementation GDCFirebaseChannel {
18+
19+
}
20+
- (instancetype)initWithClientId:(NSString *)clientId {
21+
self = [super init];
22+
if (self) {
23+
_clientId = clientId;
24+
_bufRef = [FIRDatabase.database referenceWithPath:@"bus"];
25+
_replyTopics = @{}.mutableCopy;
26+
27+
__weak GDCFirebaseChannel *weakSelf = self;
28+
[[[_bufRef child:@"queue"] child:clientId] observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
29+
NSDictionary *msg = snapshot.value[@"send"];
30+
NSString *topic = [clientId stringByAppendingPathComponent:msg[@"topic"]];
31+
id payload = msg[payloadKey];
32+
GDCOptions *options = [GDCOptions parseFromJson:msg[optionsKey] error:nil];
33+
[weakSelf.bus sendLocal:topic payload:payload options:options replyHandler:^(id <GDCAsyncResult> asyncResult) {
34+
GDCMessageImpl *msg = asyncResult.result;
35+
NSDictionary *reply = [msg toJsonWithTopic:NO];
36+
[[snapshot.ref child:@"reply"] setValue:reply];
37+
[snapshot.ref onDisconnectRemoveValue];
38+
}];
39+
}];
40+
}
41+
42+
return self;
43+
}
44+
45+
- (void)goOnline:(id)clientInfo {
46+
[FIRDatabase.database goOnline];
47+
self.bufRef = [[FIRDatabase.database reference] child:@"bus"];
48+
FIRDatabaseReference *clientIdRef = [[self.bufRef child:@"clients"] child:self.clientId];
49+
[clientIdRef onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
50+
if (error) {
51+
return;
52+
}
53+
[clientIdRef setValue:clientInfo];
54+
}];
55+
}
56+
57+
- (void)reportMessage:(GDCMessageImpl *)message {
58+
if (message.payload && (
59+
![message.payload conformsToProtocol:@protocol(GDCSerializable)] && ![message.payload isKindOfClass:NSString.class] &&
60+
![message.payload isKindOfClass:NSNumber.class] && ![message.payload isKindOfClass:NSArray.class] && ![message.payload isKindOfClass:NSDictionary.class])) {
61+
return;
62+
}
63+
NSString *topic = message.topic;
64+
NSString *historyPath = nil;
65+
if ([topic hasPrefix:@"reply/"]) {
66+
if (!self.replyTopics[topic]) {
67+
return;
68+
}
69+
historyPath = self.replyTopics[topic];
70+
[self.replyTopics removeObjectForKey:topic];
71+
NSMutableDictionary *value = [message toJsonWithTopic:NO];
72+
value[@"topic"] = nil;
73+
[[[self.bufRef child:historyPath] child:@"reply"] setValue:value];
74+
return;
75+
}
76+
if ([topic hasPrefix:[GDCBusProvider.clientId stringByAppendingString:@"/"]]) {
77+
topic = [topic substringFromIndex:GDCBusProvider.clientId.length + 1];
78+
}
79+
historyPath = [NSString stringWithFormat:@"history/%@/messages/", [topic stringByReplacingOccurrencesOfString:@"/" withString:@"_"]];
80+
FIRDatabaseReference *historyRef = [self.bufRef child:historyPath].childByAutoId;
81+
historyPath = [historyPath stringByAppendingPathComponent:historyRef.key];
82+
if (message.replyTopic) {
83+
self.replyTopics[message.replyTopic] = historyPath;
84+
}
85+
NSMutableDictionary *msg = @{}.mutableCopy;
86+
msg[@"client"] = self.clientId;
87+
msg[@"send"] = [message toJsonWithTopic:NO];
88+
msg[@"send"][@"topic"] = topic;
89+
msg[@"send"][@"replyTopic"] = nil;
90+
91+
NSMutableDictionary *values = @{}.mutableCopy;
92+
values[historyPath] = msg;
93+
94+
NSString *categoryPath = @"category";
95+
NSMutableDictionary *categoryValue = @{}.mutableCopy;
96+
NSRange range = [topic rangeOfString:@"/"];
97+
NSUInteger index = range.location;
98+
if (index != NSNotFound) {
99+
categoryPath = [NSString stringWithFormat:@"%@/%@/topics/%@", categoryPath, [topic substringToIndex:index],
100+
[[topic substringFromIndex:index + 1] stringByReplacingOccurrencesOfString:@"/" withString:@"_"]];
101+
} else {
102+
categoryPath = [categoryPath stringByAppendingPathComponent:topic];
103+
}
104+
categoryValue[@"version"] = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
105+
values[categoryPath] = categoryValue;
106+
107+
[self.bufRef updateChildValues:values];
108+
}
109+
@end

0 commit comments

Comments
 (0)