@wisdomgarden/capacitor-plugin-beacon 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -0
- package/WisdomgardenCapacitorPluginBeacon.podspec +17 -0
- package/android/build.gradle +52 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradle.properties +24 -0
- package/android/gradlew +188 -0
- package/android/gradlew.bat +100 -0
- package/android/proguard-rules.pro +21 -0
- package/android/settings.gradle +2 -0
- package/android/src/androidTest/java/com/getcapacitor/android/ExampleInstrumentedTest.java +26 -0
- package/android/src/main/AndroidManifest.xml +20 -0
- package/android/src/main/java/com/wisdomgarden/mobile/beacon/Beacon.java +294 -0
- package/android/src/main/java/com/wisdomgarden/mobile/beacon/BeaconUtils.java +118 -0
- package/android/src/main/res/layout/bridge_layout_main.xml +15 -0
- package/android/src/main/res/values/colors.xml +3 -0
- package/android/src/main/res/values/strings.xml +3 -0
- package/android/src/main/res/values/styles.xml +3 -0
- package/android/src/test/java/com/getcapacitor/ExampleUnitTest.java +18 -0
- package/dist/esm/definitions.d.ts +49 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +25 -0
- package/dist/esm/web.js +61 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.js +70 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/BeaconUtils.swift +103 -0
- package/ios/Plugin/Info.plist +30 -0
- package/ios/Plugin/Plugin.h +10 -0
- package/ios/Plugin/Plugin.m +14 -0
- package/ios/Plugin/Plugin.swift +342 -0
- package/ios/Plugin.xcodeproj/project.pbxproj +556 -0
- package/ios/Plugin.xcodeproj/xcuserdata/peixinliu.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/ios/Plugin.xcworkspace/contents.xcworkspacedata +10 -0
- package/ios/Plugin.xcworkspace/xcuserdata/peixinliu.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/PluginTests/Info.plist +22 -0
- package/ios/PluginTests/PluginTests.swift +35 -0
- package/ios/Podfile +16 -0
- package/ios/Podfile.lock +22 -0
- package/ios/Pods/Local Podspecs/Capacitor.podspec.json +30 -0
- package/ios/Pods/Local Podspecs/CapacitorCordova.podspec.json +22 -0
- package/ios/Pods/Manifest.lock +22 -0
- package/ios/Pods/Pods.xcodeproj/project.pbxproj +1381 -0
- package/ios/Pods/Pods.xcodeproj/xcuserdata/peixinliu.xcuserdatad/xcschemes/Capacitor.xcscheme +58 -0
- package/ios/Pods/Pods.xcodeproj/xcuserdata/peixinliu.xcuserdatad/xcschemes/CapacitorCordova.xcscheme +58 -0
- package/ios/Pods/Pods.xcodeproj/xcuserdata/peixinliu.xcuserdatad/xcschemes/Pods-Plugin.xcscheme +58 -0
- package/ios/Pods/Pods.xcodeproj/xcuserdata/peixinliu.xcuserdatad/xcschemes/Pods-PluginTests.xcscheme +58 -0
- package/ios/Pods/Pods.xcodeproj/xcuserdata/peixinliu.xcuserdatad/xcschemes/xcschememanagement.plist +39 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor-Info.plist +26 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor-dummy.m +5 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor-prefix.pch +12 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor-umbrella.h +23 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor.debug.xcconfig +16 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor.modulemap +6 -0
- package/ios/Pods/Target Support Files/Capacitor/Capacitor.release.xcconfig +16 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-Info.plist +26 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-dummy.m +5 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-prefix.pch +12 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-umbrella.h +33 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.debug.xcconfig +13 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.modulemap +6 -0
- package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.release.xcconfig +13 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-Info.plist +26 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-acknowledgements.markdown +3 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-acknowledgements.plist +29 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-dummy.m +5 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-umbrella.h +16 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.debug.xcconfig +14 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.modulemap +6 -0
- package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig +14 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-Info.plist +26 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-acknowledgements.markdown +3 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-acknowledgements.plist +29 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-dummy.m +5 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-frameworks.sh +188 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-umbrella.h +16 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig +15 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.modulemap +6 -0
- package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig +15 -0
- package/package.json +64 -0
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
var capacitorPlugin = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var __awaiter = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
7
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
8
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
class BeaconWeb extends core.WebPlugin {
|
|
14
|
+
constructor() {
|
|
15
|
+
super({
|
|
16
|
+
name: 'Beacon',
|
|
17
|
+
platforms: ['web'],
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
initialize(_options) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
//
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
startBroadcasting(_options) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
//
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
stopBroadcasting() {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
//
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
startMonitoring() {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
//
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
stopMonitoring() {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
//
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
cleanup() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
//
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
parseMessage(_options) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
return {
|
|
53
|
+
rollcallId: 0,
|
|
54
|
+
nonce: '',
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const Beacon = new BeaconWeb();
|
|
60
|
+
core.registerWebPlugin(Beacon);
|
|
61
|
+
|
|
62
|
+
exports.Beacon = Beacon;
|
|
63
|
+
exports.BeaconWeb = BeaconWeb;
|
|
64
|
+
|
|
65
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
66
|
+
|
|
67
|
+
return exports;
|
|
68
|
+
|
|
69
|
+
})({}, capacitorExports);
|
|
70
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/web.js"],"sourcesContent":["var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { WebPlugin } from '@capacitor/core';\nexport class BeaconWeb extends WebPlugin {\n constructor() {\n super({\n name: 'Beacon',\n platforms: ['web'],\n });\n }\n initialize(_options) {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n startBroadcasting(_options) {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n stopBroadcasting() {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n startMonitoring() {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n stopMonitoring() {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n cleanup() {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n parseMessage(_options) {\n return __awaiter(this, void 0, void 0, function* () {\n return {\n rollcallId: 0,\n nonce: '',\n };\n });\n }\n}\nconst Beacon = new BeaconWeb();\nexport { Beacon };\nimport { registerWebPlugin } from '@capacitor/core';\nregisterWebPlugin(Beacon);\n//# sourceMappingURL=web.js.map"],"names":["this","WebPlugin","registerWebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public struct BeaconUtils {
|
|
4
|
+
public static let WG_UUID = "1ed18c59-a7cc-4752-96b0-51d77a456584"
|
|
5
|
+
public static let message_max_length = 11
|
|
6
|
+
|
|
7
|
+
private static let chars =
|
|
8
|
+
"2O9AuFNPDx4gtJwS3ye7l1Mq0dEB5HsaKInikRmLhjpG6b8fzQrCcvo"
|
|
9
|
+
private static let radix = chars.count
|
|
10
|
+
|
|
11
|
+
public static func encode(_ num: Int) -> String {
|
|
12
|
+
if num == 0 { return String(chars[chars.startIndex]) }
|
|
13
|
+
var result = ""
|
|
14
|
+
let isNegative = num < 0
|
|
15
|
+
var n = abs(num)
|
|
16
|
+
|
|
17
|
+
while n > 0 {
|
|
18
|
+
let remainder = n % radix
|
|
19
|
+
let char = chars[chars.index(chars.startIndex, offsetBy: remainder)]
|
|
20
|
+
result = String(char) + result
|
|
21
|
+
n /= radix
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return isNegative ? "-" + result : result
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static func decode(_ str: String) -> Int {
|
|
28
|
+
var num = 0
|
|
29
|
+
for char in str {
|
|
30
|
+
if let index = chars.firstIndex(of: char) {
|
|
31
|
+
num =
|
|
32
|
+
num * radix
|
|
33
|
+
+ chars.distance(from: chars.startIndex, to: index)
|
|
34
|
+
} else {
|
|
35
|
+
return 0
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return num
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public static func parseMessage(_ message: String?) -> [String: Any] {
|
|
42
|
+
var payload: [String: Any] = [
|
|
43
|
+
"rollcallId": 0,
|
|
44
|
+
"nonce": "",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
guard let message = message else {
|
|
48
|
+
return payload
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if message.count < message_max_length {
|
|
52
|
+
return payload
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 检查字符是否为 nonce 字母,T-Z
|
|
56
|
+
func isNonceLetter(_ c: Character) -> Bool {
|
|
57
|
+
let code = c.asciiValue ?? 0
|
|
58
|
+
return code >= 84 && code <= 90
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (i, char) in message.enumerated() {
|
|
62
|
+
if isNonceLetter(char) {
|
|
63
|
+
let rollcallIdStr = String(
|
|
64
|
+
message[
|
|
65
|
+
..<message.index(
|
|
66
|
+
message.startIndex,
|
|
67
|
+
offsetBy: i
|
|
68
|
+
)
|
|
69
|
+
]
|
|
70
|
+
)
|
|
71
|
+
payload["rollcallId"] = decode(rollcallIdStr)
|
|
72
|
+
|
|
73
|
+
let nonceStr = String(
|
|
74
|
+
message[
|
|
75
|
+
message.index(
|
|
76
|
+
message.startIndex,
|
|
77
|
+
offsetBy: i
|
|
78
|
+
)...
|
|
79
|
+
]
|
|
80
|
+
)
|
|
81
|
+
payload["nonce"] = nonceStr
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return payload
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 如果rollcallid 过长,挤占了 message 的长度,导致数据不全,可能会出错,这个数量级需要 id 都在千万级别,一般达不到
|
|
90
|
+
public static func buildMessage(rollcallId: Int, nonce: String) -> String {
|
|
91
|
+
let rollcallIdStr = encode(rollcallId)
|
|
92
|
+
|
|
93
|
+
guard !nonce.isEmpty, let firstChar = nonce.first else {
|
|
94
|
+
return rollcallIdStr + "Z"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let remainingChars = String(nonce.dropFirst())
|
|
98
|
+
|
|
99
|
+
let message = rollcallIdStr + nonce
|
|
100
|
+
return message.count > message_max_length
|
|
101
|
+
? String(message.prefix(message_max_length)) : message
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>FMWK</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
21
|
+
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
|
22
|
+
<string>Location permission is required to detect the Beacon.</string>
|
|
23
|
+
<key>NSLocationWhenInUseUsageDescription</key>
|
|
24
|
+
<string>Location permission is required to detect the Beacon.</string>
|
|
25
|
+
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
26
|
+
<string> Bluetooth is needed to broadcast the Beacon signal.</string>
|
|
27
|
+
<key>NSPrincipalClass</key>
|
|
28
|
+
<string></string>
|
|
29
|
+
</dict>
|
|
30
|
+
</plist>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
//! Project version number for Plugin.
|
|
4
|
+
FOUNDATION_EXPORT double PluginVersionNumber;
|
|
5
|
+
|
|
6
|
+
//! Project version string for Plugin.
|
|
7
|
+
FOUNDATION_EXPORT const unsigned char PluginVersionString[];
|
|
8
|
+
|
|
9
|
+
// In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
|
|
10
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <Capacitor/Capacitor.h>
|
|
2
|
+
#import <Foundation/Foundation.h>
|
|
3
|
+
|
|
4
|
+
// Define the plugin using the CAP_PLUGIN Macro, and
|
|
5
|
+
// each method the plugin supports using the CAP_PLUGIN_METHOD macro.
|
|
6
|
+
CAP_PLUGIN(Beacon, "Beacon",
|
|
7
|
+
CAP_PLUGIN_METHOD(initialize, CAPPluginReturnPromise);
|
|
8
|
+
CAP_PLUGIN_METHOD(startBroadcasting, CAPPluginReturnPromise);
|
|
9
|
+
CAP_PLUGIN_METHOD(stopBroadcasting, CAPPluginReturnPromise);
|
|
10
|
+
CAP_PLUGIN_METHOD(startMonitoring, CAPPluginReturnPromise);
|
|
11
|
+
CAP_PLUGIN_METHOD(stopMonitoring, CAPPluginReturnPromise);
|
|
12
|
+
CAP_PLUGIN_METHOD(cleanup, CAPPluginReturnPromise);
|
|
13
|
+
CAP_PLUGIN_METHOD(parseMessage, CAPPluginReturnPromise);
|
|
14
|
+
)
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import Capacitor
|
|
2
|
+
import CoreBluetooth
|
|
3
|
+
import CoreLocation
|
|
4
|
+
import Foundation
|
|
5
|
+
|
|
6
|
+
/// Please read the Capacitor iOS Plugin Development Guide
|
|
7
|
+
/// here: https://capacitorjs.com/docs/plugins/ios
|
|
8
|
+
@objc(Beacon)
|
|
9
|
+
public class Beacon: CAPPlugin, CBPeripheralManagerDelegate,
|
|
10
|
+
CBCentralManagerDelegate
|
|
11
|
+
{
|
|
12
|
+
private var peripheralManager: CBPeripheralManager?
|
|
13
|
+
private var centralManager: CBCentralManager?
|
|
14
|
+
|
|
15
|
+
private var isBroadcasting: Bool = false
|
|
16
|
+
private var needBroadcasting: Bool = false
|
|
17
|
+
|
|
18
|
+
private var isMonitoring: Bool = false
|
|
19
|
+
private var needMonitoring: Bool = false
|
|
20
|
+
|
|
21
|
+
private var allowDuplicatesKey = true
|
|
22
|
+
|
|
23
|
+
private var rollcallId = 0
|
|
24
|
+
private var nonce = ""
|
|
25
|
+
private var message = ""
|
|
26
|
+
|
|
27
|
+
@objc func parseMessage(_ call: CAPPluginCall) {
|
|
28
|
+
let message = call.getString("message")
|
|
29
|
+
let result = BeaconUtils.parseMessage(message)
|
|
30
|
+
call.resolve(result)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@objc func initialize(_ call: CAPPluginCall) {
|
|
34
|
+
allowDuplicatesKey = call.getBool("allowDuplicatesKey") ?? true
|
|
35
|
+
call.resolve()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
func startAdvertising() {
|
|
39
|
+
super.bridge.logToJs("[Debug] startAdvertising 12")
|
|
40
|
+
if peripheralManager == nil {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if isBroadcasting == true {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
super.bridge.logToJs("[Debug] startAdvertising broadcasting 13")
|
|
48
|
+
isBroadcasting = true
|
|
49
|
+
|
|
50
|
+
let advertisementData: [String: Any] = [
|
|
51
|
+
CBAdvertisementDataServiceUUIDsKey: [CBUUID(string: BeaconUtils.WG_UUID)],
|
|
52
|
+
CBAdvertisementDataLocalNameKey: message,
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
super.bridge.logToJs("[Debug] startAdvertising broadcasting 14")
|
|
56
|
+
peripheralManager?.startAdvertising(advertisementData)
|
|
57
|
+
super.bridge.logToJs("[Debug] startAdvertising broadcasting 15")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@objc func startBroadcasting(_ call: CAPPluginCall) {
|
|
61
|
+
super.bridge.logToJs("[Debug] startBroadcasting 11")
|
|
62
|
+
|
|
63
|
+
if let message = call.getString("message"),
|
|
64
|
+
message.count == BeaconUtils.message_max_length
|
|
65
|
+
{
|
|
66
|
+
self.message = message
|
|
67
|
+
} else {
|
|
68
|
+
guard let rollcallId = call.getInt("rollcallId") else {
|
|
69
|
+
call.reject("rollcallId is required")
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
guard let nonce = call.getString("nonce") else {
|
|
73
|
+
call.reject("nonce is required")
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
self.rollcallId = rollcallId
|
|
78
|
+
self.nonce = nonce
|
|
79
|
+
|
|
80
|
+
self.message = BeaconUtils.buildMessage(rollcallId: rollcallId, nonce: nonce)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
super.bridge.logToJs("[Debug] startBroadcasting 11.1")
|
|
84
|
+
|
|
85
|
+
if isBroadcasting {
|
|
86
|
+
call.resolve()
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
super.bridge.logToJs("[Debug] startBroadcasting 11.2")
|
|
90
|
+
|
|
91
|
+
needBroadcasting = true
|
|
92
|
+
|
|
93
|
+
if peripheralManager == nil {
|
|
94
|
+
peripheralManager = CBPeripheralManager(
|
|
95
|
+
delegate: self,
|
|
96
|
+
queue: nil
|
|
97
|
+
)
|
|
98
|
+
super.bridge.logToJs("[Debug] startBroadcasting 11.2.1")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if peripheralManager?.state == .poweredOn {
|
|
102
|
+
self.startAdvertising()
|
|
103
|
+
super.bridge.logToJs("[Debug] startBroadcasting 11.2.2")
|
|
104
|
+
}
|
|
105
|
+
super.bridge.logToJs("[Debug] startBroadcasting 11.3")
|
|
106
|
+
|
|
107
|
+
call.resolve()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@objc func stopBroadcasting(_ call: CAPPluginCall) {
|
|
111
|
+
peripheralManager?.stopAdvertising()
|
|
112
|
+
isBroadcasting = false
|
|
113
|
+
needBroadcasting = false
|
|
114
|
+
call.resolve()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
func scanForPeripherals() {
|
|
118
|
+
super.bridge.logToJs("[Debug] scanForPeripherals 22")
|
|
119
|
+
if centralManager == nil {
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if isMonitoring == true {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
super.bridge.logToJs("[Debug] scanForPeripherals monitoring 23")
|
|
127
|
+
isMonitoring = true
|
|
128
|
+
|
|
129
|
+
let options: [String: Any] = [
|
|
130
|
+
CBCentralManagerScanOptionAllowDuplicatesKey: allowDuplicatesKey,
|
|
131
|
+
CBCentralManagerScanOptionSolicitedServiceUUIDsKey: [
|
|
132
|
+
CBUUID(string: BeaconUtils.WG_UUID)
|
|
133
|
+
],
|
|
134
|
+
]
|
|
135
|
+
super.bridge.logToJs("[Debug] scanForPeripherals monitoring 24")
|
|
136
|
+
|
|
137
|
+
centralManager?.scanForPeripherals(
|
|
138
|
+
withServices: [CBUUID(string: BeaconUtils.WG_UUID)],
|
|
139
|
+
options: options
|
|
140
|
+
)
|
|
141
|
+
super.bridge.logToJs("[Debug] scanForPeripherals monitoring 25")
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@objc func startMonitoring(_ call: CAPPluginCall) {
|
|
145
|
+
super.bridge.logToJs("[Debug] startMonitoring 21")
|
|
146
|
+
if isMonitoring {
|
|
147
|
+
call.resolve()
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
needMonitoring = true
|
|
151
|
+
super.bridge.logToJs("[Debug] startMonitoring 21.1")
|
|
152
|
+
|
|
153
|
+
if centralManager == nil {
|
|
154
|
+
centralManager = CBCentralManager(delegate: self, queue: nil)
|
|
155
|
+
super.bridge.logToJs("[Debug] startMonitoring 21.1.1")
|
|
156
|
+
}
|
|
157
|
+
super.bridge.logToJs("[Debug] startMonitoring 21.2")
|
|
158
|
+
|
|
159
|
+
if centralManager?.state == .poweredOn {
|
|
160
|
+
super.bridge.logToJs("[Debug] startMonitoring 21.2.1")
|
|
161
|
+
self.scanForPeripherals()
|
|
162
|
+
}
|
|
163
|
+
super.bridge.logToJs("[Debug] startMonitoring 21.3")
|
|
164
|
+
|
|
165
|
+
call.resolve()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@objc func stopMonitoring(_ call: CAPPluginCall) {
|
|
169
|
+
centralManager?.stopScan()
|
|
170
|
+
isMonitoring = false
|
|
171
|
+
needMonitoring = false
|
|
172
|
+
call.resolve()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@objc func cleanup(_ call: CAPPluginCall) {
|
|
176
|
+
peripheralManager?.stopAdvertising()
|
|
177
|
+
centralManager?.stopScan()
|
|
178
|
+
|
|
179
|
+
peripheralManager = nil
|
|
180
|
+
centralManager = nil
|
|
181
|
+
isBroadcasting = false
|
|
182
|
+
isMonitoring = false
|
|
183
|
+
needBroadcasting = false
|
|
184
|
+
needMonitoring = false
|
|
185
|
+
|
|
186
|
+
self.removeAllListeners(call)
|
|
187
|
+
call.resolve()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// MARK: - CBPeripheralManagerDelegate
|
|
191
|
+
public func peripheralManagerDidUpdateState(
|
|
192
|
+
_ peripheral: CBPeripheralManager
|
|
193
|
+
) {
|
|
194
|
+
super.bridge.logToJs(
|
|
195
|
+
"[Beacon] Peripheral manager state changed to: \(peripheral.state.rawValue)"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
switch peripheral.state {
|
|
199
|
+
case .poweredOn:
|
|
200
|
+
super.bridge.logToJs("[Beacon] Peripheral manager is powered on")
|
|
201
|
+
notifyListeners(
|
|
202
|
+
"stateUpdated",
|
|
203
|
+
data: ["type": "peripheral", "state": "poweredOn"]
|
|
204
|
+
)
|
|
205
|
+
case .poweredOff:
|
|
206
|
+
super.bridge.logToJs("[Beacon] Peripheral manager is powered off")
|
|
207
|
+
notifyListeners(
|
|
208
|
+
"stateUpdated",
|
|
209
|
+
data: ["type": "peripheral", "state": "poweredOff"]
|
|
210
|
+
)
|
|
211
|
+
case .unauthorized:
|
|
212
|
+
super.bridge.logToJs("[Beacon] Peripheral manager is unauthorized")
|
|
213
|
+
notifyListeners(
|
|
214
|
+
"stateUpdated",
|
|
215
|
+
data: ["type": "peripheral", "state": "unauthorized"]
|
|
216
|
+
)
|
|
217
|
+
case .unsupported:
|
|
218
|
+
super.bridge.logToJs("[Beacon] Peripheral manager is unsupported")
|
|
219
|
+
notifyListeners(
|
|
220
|
+
"stateUpdated",
|
|
221
|
+
data: ["type": "peripheral", "state": "unsupported"]
|
|
222
|
+
)
|
|
223
|
+
default:
|
|
224
|
+
super.bridge.logToJs(
|
|
225
|
+
"[Beacon] Peripheral manager state: \(peripheral.state.rawValue)"
|
|
226
|
+
)
|
|
227
|
+
notifyListeners(
|
|
228
|
+
"stateUpdated",
|
|
229
|
+
data: [
|
|
230
|
+
"type": "peripheral", "state": peripheral.state.rawValue,
|
|
231
|
+
]
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if needBroadcasting {
|
|
236
|
+
if peripheral.state == .poweredOn {
|
|
237
|
+
super.bridge.logToJs(
|
|
238
|
+
"[Debug] peripheralManagerDidUpdateState needBroadcasting poweredOn"
|
|
239
|
+
)
|
|
240
|
+
self.startAdvertising()
|
|
241
|
+
} else {
|
|
242
|
+
super.bridge.logToJs(
|
|
243
|
+
"[Debug] peripheralManagerDidUpdateState needBroadcasting but stopAdvertising"
|
|
244
|
+
)
|
|
245
|
+
peripheralManager?.stopAdvertising()
|
|
246
|
+
isBroadcasting = false
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// MARK: - CBCentralManagerDelegate
|
|
252
|
+
|
|
253
|
+
public func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
|
254
|
+
super.bridge.logToJs(
|
|
255
|
+
"[Beacon] Central manager state changed to: \(central.state.rawValue)"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
switch central.state {
|
|
259
|
+
case .poweredOn:
|
|
260
|
+
super.bridge.logToJs("[Beacon] Central manager is powered on")
|
|
261
|
+
notifyListeners("bluetoothStateChanged", data: ["enabled": true])
|
|
262
|
+
case .poweredOff:
|
|
263
|
+
super.bridge.logToJs("[Beacon] Central manager is powered off")
|
|
264
|
+
notifyListeners(
|
|
265
|
+
"stateError",
|
|
266
|
+
data: ["type": "central", "state": "poweredOff"]
|
|
267
|
+
)
|
|
268
|
+
notifyListeners("bluetoothStateChanged", data: ["enabled": false])
|
|
269
|
+
case .unauthorized:
|
|
270
|
+
super.bridge.logToJs("[Beacon] Central manager is unauthorized")
|
|
271
|
+
notifyListeners(
|
|
272
|
+
"stateError",
|
|
273
|
+
data: ["type": "central", "state": "unauthorized"]
|
|
274
|
+
)
|
|
275
|
+
notifyListeners(
|
|
276
|
+
"bluetoothStateChanged",
|
|
277
|
+
data: ["enabled": false, "error": "unauthorized"]
|
|
278
|
+
)
|
|
279
|
+
case .unsupported:
|
|
280
|
+
super.bridge.logToJs("[Beacon] Central manager is unsupported")
|
|
281
|
+
notifyListeners(
|
|
282
|
+
"stateError",
|
|
283
|
+
data: ["type": "central", "state": "unsupported"]
|
|
284
|
+
)
|
|
285
|
+
notifyListeners(
|
|
286
|
+
"bluetoothStateChanged",
|
|
287
|
+
data: ["enabled": false, "error": "unsupported"]
|
|
288
|
+
)
|
|
289
|
+
default:
|
|
290
|
+
super.bridge.logToJs(
|
|
291
|
+
"[Beacon] Central manager state: \(central.state.rawValue)"
|
|
292
|
+
)
|
|
293
|
+
notifyListeners(
|
|
294
|
+
"stateError",
|
|
295
|
+
data: ["type": "central", "state": central.state.rawValue]
|
|
296
|
+
)
|
|
297
|
+
notifyListeners(
|
|
298
|
+
"bluetoothStateChanged",
|
|
299
|
+
data: ["enabled": false, "error": "unknown"]
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if needMonitoring {
|
|
304
|
+
if central.state == .poweredOn {
|
|
305
|
+
super.bridge.logToJs(
|
|
306
|
+
"[Debug] centralManagerDidUpdateState needMonitoring poweredOn"
|
|
307
|
+
)
|
|
308
|
+
self.scanForPeripherals()
|
|
309
|
+
} else {
|
|
310
|
+
super.bridge.logToJs(
|
|
311
|
+
"[Debug] centralManagerDidUpdateState needMonitoring but stopScan"
|
|
312
|
+
)
|
|
313
|
+
centralManager?.stopScan()
|
|
314
|
+
isMonitoring = false
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
public func centralManager(
|
|
320
|
+
_ central: CBCentralManager,
|
|
321
|
+
didDiscover peripheral: CBPeripheral,
|
|
322
|
+
advertisementData: [String: Any],
|
|
323
|
+
rssi RSSI: NSNumber
|
|
324
|
+
) {
|
|
325
|
+
if let message = advertisementData[CBAdvertisementDataLocalNameKey]
|
|
326
|
+
as? String
|
|
327
|
+
{
|
|
328
|
+
let peripheralId = peripheral.identifier.uuidString
|
|
329
|
+
let rssiValue = RSSI.intValue
|
|
330
|
+
|
|
331
|
+
notifyListeners(
|
|
332
|
+
"beaconReceived",
|
|
333
|
+
data: [
|
|
334
|
+
"message": message,
|
|
335
|
+
"rssi": rssiValue,
|
|
336
|
+
"peripheralId": peripheralId,
|
|
337
|
+
"timestamp": Int64(Date().timeIntervalSince1970 * 1000),
|
|
338
|
+
]
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|