├── .gitattributes
├── AimeInterfaceProvider
├── Assets.xcassets
│ ├── Contents.json
│ ├── reader.imageset
│ │ ├── aime.png
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ ├── logo.png
│ │ └── Contents.json
├── AimeInterfaceProvider-Bridging-Header.h
├── AimeInterfaceProvider.entitlements
├── FeliCaReader
│ ├── FeliCaReaderDelegate.swift
│ ├── FeliCaCard.swift
│ └── FeliCaReader.swift
├── CardCell.swift
├── Extension
│ ├── Data.swift
│ └── FixedWidthInteger.swift
├── SocketDelegate.h
├── AppDelegate.swift
├── CardTableViewController.swift
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Info.plist
├── SceneDelegate.swift
├── ViewController.swift
└── SocketDelegate.m
├── AimeInterfaceProvider.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
└── project.pbxproj
├── LICENSE
├── README.md
└── .gitignore
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Assets.xcassets/reader.imageset/aime.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyyr-p/AimeInterfaceProvider-iOS/HEAD/AimeInterfaceProvider/Assets.xcassets/reader.imageset/aime.png
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Assets.xcassets/AppIcon.appiconset/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyyr-p/AimeInterfaceProvider-iOS/HEAD/AimeInterfaceProvider/Assets.xcassets/AppIcon.appiconset/logo.png
--------------------------------------------------------------------------------
/AimeInterfaceProvider/AimeInterfaceProvider-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import "SocketDelegate.h"
6 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/AimeInterfaceProvider.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.nfc.readersession.formats
6 |
7 | NDEF
8 | TAG
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Assets.xcassets/reader.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "aime.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "originHash" : "339f3a13d3317f1341228fbeac4e5beb8f40c79a455e08adbe47f329e7a56d72",
3 | "pins" : [
4 | {
5 | "identity" : "cocoaasyncsocket",
6 | "kind" : "remoteSourceControl",
7 | "location" : "https://github.com/robbiehanson/CocoaAsyncSocket.git",
8 | "state" : {
9 | "revision" : "dbdc00669c1ced63b27c3c5f052ee4d28f10150c",
10 | "version" : "7.6.5"
11 | }
12 | }
13 | ],
14 | "version" : 3
15 | }
16 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/FeliCaReader/FeliCaReaderDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FeliCaReaderDelegate.swift
3 | // nfc
4 | //
5 | // Created by kalan on 2019/10/22.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | public protocol FeliCaReaderDelegate {
10 | var reader: FeliCaReader? { get }
11 |
12 | func readerDidBecomeActive(_ reader: FeliCaReader) -> Void
13 | func feliCaReader(_ reader: FeliCaReader, withError error: Error) -> Void
14 | func feliCaReader(_ reader: FeliCaReader, idmpmm card: Data) -> Void
15 | }
16 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/CardCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CardCell.swift
3 | // nfc
4 | //
5 | // Created by ST22245 on 2019/10/23.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CardCell: UITableViewCell {
12 | @IBOutlet weak var title: UILabel!
13 | @IBOutlet weak var entry: UILabel!
14 | @IBOutlet weak var date: UILabel!
15 | @IBOutlet weak var exit: UILabel!
16 | @IBOutlet weak var machineType: UILabel!
17 | @IBOutlet weak var usageType: UILabel!
18 | @IBOutlet weak var paymentType: UILabel!
19 | @IBOutlet weak var entryExitType: UILabel!
20 | }
21 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Extension/Data.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Data.swift
3 | // nfc
4 | //
5 | // Created by yyyr on 2025/1/24.
6 | // Copyright © 2025 kalan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Data {
12 | struct HexEncodingOptions: OptionSet {
13 | let rawValue: Int
14 | static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
15 | }
16 |
17 | func hexEncodedString(options: HexEncodingOptions = []) -> String {
18 | let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
19 | return self.map { String(format: format, $0) }.joined()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/SocketDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // SocketDelegate.h
3 | // Brokenithm-iOS
4 | //
5 | // Created by ester on 2020/2/29.
6 | // Copyright © 2020 esterTion. All rights reserved.
7 | //
8 |
9 | #ifndef SocketDelegate_h
10 | #define SocketDelegate_h
11 |
12 | @class ViewController;
13 |
14 | #import
15 | #import
16 |
17 | @interface SocketDelegate : NSObject {
18 | GCDAsyncSocket *server;
19 | NSMutableArray *connectedSockets;
20 | }
21 | @property ViewController *viewController;
22 |
23 | - (void)BroadcastFeliCaData:(NSData*)data;
24 | - (void)BroadcastData:(NSData*)data;
25 |
26 | @end
27 |
28 | #endif /* SocketDelegate_h */
29 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Extension/FixedWidthInteger.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Data.swift
3 | // nfc
4 | //
5 | // Created by kalan on 2019/10/22.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension FixedWidthInteger {
12 | init(bytes: UInt8...) {
13 | self.init(bytes: bytes)
14 | }
15 |
16 | init(bytes: T) {
17 | let count = bytes.count - 1
18 | self = bytes.enumerated().reduce(into: 0) { (result, item) in
19 | result += Self(item.element) << (8 * (count - item.offset))
20 | }
21 | }
22 |
23 | var data: Data {
24 | let data = withUnsafeBytes(of: self) { Data($0) }
25 | return data
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (C) 2025 yyyr Network
4 | Copyright (c) 2020 Kalan
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AimeInterfaceProvider-iOS
2 |
3 | A project modified from [something cool with CoreNFC](https://github.com/kjj6198/swift-core-nfc-reader).
4 |
5 | ## Tips
6 |
7 | - Run [aimeio-socket-client](https://github.com/yyyr-p/aimeio-socket-client) on your computer.
8 | - Connect them with a USB cable. It runs on usbmuxd.
9 | - Mount [aimeio-socket](https://github.com/yyyr-p/aimeio-socket).dll into some mysterious injecting tool?
10 | - FeliCa™ Cards only at the moment.
11 |
12 | ## Requirements
13 |
14 | - iOS 14.0 or later
15 | - CoreNFC
16 |
17 | **Attention**: You need an Apple Developer Account to sign apps with CoreNFC entitlements. TrollStore *may* work, but ~~I haven't tested it.~~ it doesn't work for now.
18 |
19 | ## Copyright Notice
20 |
21 | The logos and images used in this project, including the Aime logo, Aime card images, and Amusement IC logo, are the intellectual property of their respective owners. All rights to these materials are reserved. This project is for non-commercial purposes only, and any use of these materials without proper authorization is prohibited.
22 |
23 | ---
24 |
25 | Original README is below.
26 |
27 | ## FeliCa Reader
28 |
29 | FeliCa reader by [CoreNFC](https://developer.apple.com/documentation/corenfc)
30 |
31 | [Blog Post](https://blog.kalan.dev/core-nfc-suica/)
32 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // nfc
4 | //
5 | // Created by ST22245 on 2019/10/21.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
15 | // Override point for customization after application launch.
16 | return true
17 | }
18 |
19 | // MARK: UISceneSession Lifecycle
20 |
21 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
22 | // Called when a new scene session is being created.
23 | // Use this method to select a configuration to create the new scene with.
24 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
25 | }
26 |
27 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
28 | // Called when the user discards a scene session.
29 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
30 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
31 | }
32 |
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/CardTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CardTableViewController.swift
3 | // nfc
4 | //
5 | // Created by ST22245 on 2019/10/23.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CardTableViewController: UITableViewController {
12 | var card: FeliCaCard?
13 |
14 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
15 | return card?.entryExitHistory.count ?? 0
16 | }
17 |
18 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
19 | if let cell = tableView.dequeueReusableCell(withIdentifier: "cardCell", for: indexPath) as? CardCell {
20 | let history = card?.entryExitHistory[indexPath.row]
21 | cell.machineType.text = "機器類別:" + history!.machineType.description
22 | cell.paymentType.text = "付款類別:" + history!.paymentType
23 | cell.usageType.text = "使用類別:" + history!.usageType.description
24 | cell.entryExitType.text = "出入場類別:" + history!.entryExitType.description
25 |
26 | cell.date.text = "日期:\(history?.date.description ?? "0")"
27 | cell.title.text = "餘額:\(history?.balance?.description ?? "0")"
28 | cell.entry.text = "進場車站號碼:" + String(describing: history!.entryStationCode)
29 | cell.exit.text = "出場車站號碼:" + String(describing: history!.exitStationCode)
30 |
31 |
32 | return cell
33 | }
34 |
35 | return tableView.dequeueReusableCell(withIdentifier: "cardCell", for: indexPath)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "filename" : "logo.png",
35 | "idiom" : "iphone",
36 | "scale" : "2x",
37 | "size" : "60x60"
38 | },
39 | {
40 | "idiom" : "iphone",
41 | "scale" : "3x",
42 | "size" : "60x60"
43 | },
44 | {
45 | "idiom" : "ipad",
46 | "scale" : "1x",
47 | "size" : "20x20"
48 | },
49 | {
50 | "idiom" : "ipad",
51 | "scale" : "2x",
52 | "size" : "20x20"
53 | },
54 | {
55 | "idiom" : "ipad",
56 | "scale" : "1x",
57 | "size" : "29x29"
58 | },
59 | {
60 | "idiom" : "ipad",
61 | "scale" : "2x",
62 | "size" : "29x29"
63 | },
64 | {
65 | "idiom" : "ipad",
66 | "scale" : "1x",
67 | "size" : "40x40"
68 | },
69 | {
70 | "idiom" : "ipad",
71 | "scale" : "2x",
72 | "size" : "40x40"
73 | },
74 | {
75 | "idiom" : "ipad",
76 | "scale" : "1x",
77 | "size" : "76x76"
78 | },
79 | {
80 | "idiom" : "ipad",
81 | "scale" : "2x",
82 | "size" : "76x76"
83 | },
84 | {
85 | "idiom" : "ipad",
86 | "scale" : "2x",
87 | "size" : "83.5x83.5"
88 | },
89 | {
90 | "idiom" : "ios-marketing",
91 | "scale" : "1x",
92 | "size" : "1024x1024"
93 | }
94 | ],
95 | "info" : {
96 | "author" : "xcode",
97 | "version" : 1
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | # Created by https://www.gitignore.io/api/swift
3 | # Edit at https://www.gitignore.io/?templates=swift
4 |
5 | ### Swift ###
6 | # Xcode
7 | #
8 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
9 |
10 | ## Build generated
11 | build/
12 | DerivedData/
13 |
14 | ## Various settings
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata/
24 |
25 | ## Other
26 | *.moved-aside
27 | *.xccheckout
28 | *.xcscmblueprint
29 |
30 | ## Obj-C/Swift specific
31 | *.hmap
32 | *.ipa
33 | *.dSYM.zip
34 | *.dSYM
35 |
36 | ## Playgrounds
37 | timeline.xctimeline
38 | playground.xcworkspace
39 |
40 | # Swift Package Manager
41 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
42 | # Packages/
43 | # Package.pins
44 | # Package.resolved
45 | .build/
46 | # Add this line if you want to avoid checking in Xcode SPM integration.
47 | # .swiftpm/xcode
48 |
49 | # CocoaPods
50 | # We recommend against adding the Pods directory to your .gitignore. However
51 | # you should judge for yourself, the pros and cons are mentioned at:
52 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
53 | # Pods/
54 | # Add this line if you want to avoid checking in source code from the Xcode workspace
55 | # *.xcworkspace
56 |
57 | # Carthage
58 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
59 | # Carthage/Checkouts
60 |
61 | Carthage/Build
62 |
63 | # Accio dependency management
64 | Dependencies/
65 | .accio/
66 |
67 | # fastlane
68 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
69 | # screenshots whenever they are needed.
70 | # For more information about the recommended setup visit:
71 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
72 |
73 | fastlane/report.xml
74 | fastlane/Preview.html
75 | fastlane/screenshots/**/*.png
76 | fastlane/test_output
77 |
78 | # Code Injection
79 | # After new code Injection tools there's a generated folder /iOSInjectionProject
80 | # https://github.com/johnno1962/injectionforxcode
81 |
82 | iOSInjectionProject/
83 |
84 | # End of https://www.gitignore.io/api/swift
85 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Aime IO
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NFCReaderUsageDescription
26 | To read Aime card through NFC
27 | UIApplicationSceneManifest
28 |
29 | UIApplicationSupportsMultipleScenes
30 |
31 | UISceneConfigurations
32 |
33 | UIWindowSceneSessionRoleApplication
34 |
35 |
36 | UISceneConfigurationName
37 | Default Configuration
38 | UISceneDelegateClassName
39 | $(PRODUCT_MODULE_NAME).SceneDelegate
40 | UISceneStoryboardFile
41 | Main
42 |
43 |
44 |
45 |
46 | UILaunchStoryboardName
47 | LaunchScreen
48 | UIMainStoryboardFile
49 | Main
50 | UIRequiredDeviceCapabilities
51 |
52 | armv7
53 |
54 | UIStatusBarHidden
55 |
56 | UISupportedInterfaceOrientations
57 |
58 | UIInterfaceOrientationPortrait
59 |
60 | com.apple.developer.nfc.readersession.felica.systemcodes
61 |
62 | 88B4
63 | 8008
64 | 8005
65 | 0003
66 | FE00
67 |
68 | com.apple.developer.nfc.readersession.iso7816.select-identifiers
69 |
70 | D2760000850101
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // nfc
4 | //
5 | // Created by ST22245 on 2019/10/21.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftUI
11 |
12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import CoreNFC
3 |
4 | class ViewController: UIViewController, FeliCaReaderDelegate {
5 | @IBOutlet weak var background: UIImageView!
6 | var reader: FeliCaReader?
7 | var server: SocketDelegate?
8 |
9 | func readerDidBecomeActive(_ reader: FeliCaReader) {
10 | }
11 |
12 | func feliCaReader(_ reader: FeliCaReader, withError error: Error) {
13 | guard let error = error as? FeliCaTagError else {
14 | return
15 | }
16 |
17 | switch error {
18 | case .cannotConnect:
19 | reader.session?.invalidate(errorMessage: "无法与卡片建立连接")
20 | case .countExceed:
21 | reader.session?.invalidate(errorMessage: "同时检测到超过 2 张卡片,请移除后再试")
22 | case .statusError:
23 | reader.session?.invalidate(errorMessage: "卡片状态错误")
24 | case .typeMismatch:
25 | reader.session?.invalidate(errorMessage: "卡片非 FeliCa 类型")
26 | case .userCancel: break
27 | case .becomeInvalidate: break
28 | }
29 |
30 | DispatchQueue.main.async {
31 | self.startPolling()
32 | }
33 | }
34 |
35 | func feliCaReader(_ reader: FeliCaReader, idmpmm card: Data) {
36 | self.reader?.session?.alertMessage = "完成"
37 | self.reader?.session?.invalidate()
38 | self.server?.broadcastFeliCaData(card)
39 | }
40 |
41 | override func viewDidLoad() {
42 | super.viewDidLoad()
43 | server = SocketDelegate()
44 | server!.viewController = self
45 | NSLog("server created")
46 | }
47 |
48 |
49 | @IBAction func tapScan(_ sender: UIButton) {
50 | NSLog("tapScan")
51 | // startPolling()
52 | }
53 |
54 | @objc func connected() {
55 | NSLog("connected")
56 | }
57 |
58 | @objc func startPolling() {
59 | NSLog("startPolling")
60 | self.reader = FeliCaReader(delegate: self)
61 | self.reader?.beginSession()
62 | }
63 |
64 | @objc func stopPolling() {
65 | NSLog("stopPolling")
66 | self.reader?.session?.invalidate(errorMessage: "读卡停止")
67 | }
68 |
69 | @objc func updateLed(_ r: Int, _ g: Int, _ b: Int) {
70 | NSLog("updateLed")
71 | background.backgroundColor = UIColor(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: 1)
72 | }
73 |
74 | @objc func disconnected() {
75 | NSLog("disconnected")
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/FeliCaReader/FeliCaCard.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FeliCaCard.swift
3 | // nfc
4 | //
5 | // Created by kalan on 2019/10/22.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreNFC
11 | // https://www.wdic.org/w/RAIL/%E3%82%B5%E3%82%A4%E3%83%90%E3%83%8D%E8%A6%8F%E6%A0%BC%20(IC%E3%82%AB%E3%83%BC%E3%83%89)
12 |
13 | enum PaymentType: UInt, CaseIterable {
14 | case normal = 0x00
15 | case creditCard = 0x0c
16 | case pasmo = 0x0d
17 | case nimoca = 0x13
18 | case mobileApp = 0x3f
19 | }
20 |
21 | public struct FeliCaCard {
22 | var balance: Int?
23 | var entryExitHistory: [History]
24 |
25 | var systemCode: String?
26 | var idm: String?
27 |
28 | public init(_ dataList: [Data], _ idm: Data, _ systemCode: Data) {
29 | self.entryExitHistory = []
30 |
31 | for data in dataList {
32 | let paymentType = PaymentType.allCases.first(where: { UInt8($0.rawValue) == data[2] })
33 |
34 | let his = History(
35 | machineType: UInt16(data[0]),
36 | usageType: UInt16(data[1]),
37 | paymentType: String(describing: paymentType),
38 | entryExitType: UInt16(data[3]),
39 | entryStationCode: UInt16(bytes: data[6...7]),
40 | exitStationCode: UInt16(bytes: data[8...9]),
41 | date: convertToDate(data),
42 | balance: UInt(bytes: data[10...11].reversed())
43 | )
44 |
45 | self.entryExitHistory.append(his)
46 | }
47 | self.setIdm(idm: idm)
48 | self.setSystemCode(systemCode: systemCode)
49 | }
50 |
51 | private func convertToDate(_ data: Data) -> Date! {
52 | let year = data[4] >> 1
53 | let month = UInt(bytes: data[4...5]) >> 5 & 0b1111
54 | let date = data[5] & 0b11111
55 |
56 | let formatter = DateFormatter()
57 | formatter.dateFormat = "yyyy-MM-dd"
58 | formatter.locale = Locale(identifier: "en_US_POSIX")
59 | return formatter.date(from: "20\(year)-\(month)-\(date)")!
60 | }
61 |
62 | mutating func setIdm(idm: Data) {
63 | self.idm = idm.map { String(format: "%2hhx", $0) }.joined()
64 | }
65 |
66 | mutating func setSystemCode(systemCode: Data) {
67 | self.systemCode = systemCode.map { String(format: "%2hhx", $0) }.joined()
68 | }
69 | }
70 |
71 |
72 | public struct History {
73 | let machineType: UInt16
74 | let usageType: UInt16
75 | let paymentType: String
76 | let entryExitType: UInt16
77 | let entryStationCode: UInt16
78 | let exitStationCode: UInt16
79 | let date: Date
80 | let balance: UInt?
81 | }
82 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/FeliCaReader/FeliCaReader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FeliCaReader.swift
3 | // nfc
4 | //
5 | // Created by kalan on 2019/10/22.
6 | // Copyright © 2019 kalan. All rights reserved.
7 | //
8 |
9 | import CoreNFC
10 | import Foundation
11 |
12 |
13 | public enum FeliCaTagError: Error {
14 | case countExceed
15 | case typeMismatch
16 | case statusError
17 | case userCancel
18 | case becomeInvalidate
19 | case cannotConnect
20 | }
21 |
22 | @available(iOS 13.0, *)
23 | public class FeliCaReader: NSObject, NFCTagReaderSessionDelegate {
24 | internal var session: NFCTagReaderSession?
25 | internal let delegate: FeliCaReaderDelegate?
26 |
27 | private override init() {
28 | self.delegate = nil
29 | }
30 |
31 | public init(delegate: FeliCaReaderDelegate) {
32 | self.delegate = delegate
33 | }
34 |
35 | public func beginSession() {
36 | self.session = NFCTagReaderSession(pollingOption: .iso18092, delegate: self)
37 | self.session?.alertMessage = "将 Aime 卡片靠近"
38 | self.session?.begin()
39 | }
40 |
41 | public func isReadingAvailable() -> Bool {
42 | return NFCTagReaderSession.readingAvailable
43 | }
44 |
45 | public func finish(errorMessage: String?) {
46 | if errorMessage != nil {
47 | self.session?.invalidate()
48 | } else {
49 | self.session?.invalidate(errorMessage: errorMessage!)
50 | }
51 | }
52 |
53 | public func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
54 | print("tagReaderSessionDidBecomeActive(_:)")
55 | self.delegate?.readerDidBecomeActive(self)
56 | }
57 |
58 | public func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
59 | if let readerError = error as? NFCReaderError {
60 | if (readerError.code != .readerSessionInvalidationErrorFirstNDEFTagRead)
61 | && (readerError.code != .readerSessionInvalidationErrorUserCanceled) {
62 | self.delegate?.feliCaReader(self, withError: FeliCaTagError.becomeInvalidate)
63 | }
64 | }
65 | self.session = nil
66 | }
67 |
68 | public func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
69 | if tags.count > 1 {
70 | self.delegate?.feliCaReader(self, withError: FeliCaTagError.countExceed)
71 | return
72 | }
73 |
74 | let tag = tags.first!
75 |
76 | session.connect(to: tag) { (error) in
77 | guard error == nil else {
78 | session.invalidate(errorMessage: "Failed to connect")
79 | self.delegate?.feliCaReader(self, withError: FeliCaTagError.cannotConnect)
80 | return
81 | }
82 |
83 | guard case .feliCa(let feliCaTag) = tag else {
84 | self.delegate?.feliCaReader(self, withError: FeliCaTagError.typeMismatch)
85 | return
86 | }
87 |
88 | feliCaTag.polling(systemCode: feliCaTag.currentSystemCode, requestCode: NFCFeliCaPollingRequestCode.systemCode, timeSlot: NFCFeliCaPollingTimeSlot.max1, completionHandler: { (pmm, requestData, error) in
89 | if error != nil {
90 | self.delegate?.feliCaReader(self, withError: FeliCaTagError.statusError)
91 | return
92 | }
93 | var data = feliCaTag.currentIDm
94 | data.append(pmm)
95 | self.delegate?.feliCaReader(self, idmpmm: data)
96 | })
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/SocketDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // SocketDelegate.m
3 | // Brokenithm-iOS
4 | //
5 | // Created by ester on 2020/2/29.
6 | // Copyright © 2020 esterTion. All rights reserved.
7 | //
8 |
9 | #import "SocketDelegate.h"
10 | #import "AimeInterfaceProvider-Swift.h"
11 |
12 | @interface SocketDelegate ()
13 | @end
14 |
15 | @implementation SocketDelegate
16 |
17 | - (id)init {
18 | server = [[GCDAsyncSocket alloc] initWithDelegate:(id)self delegateQueue:dispatch_get_main_queue()];
19 | server.IPv4Enabled = YES;
20 | server.IPv6Enabled = YES;
21 | [self acceptConnection];
22 | connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
23 | [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(becomeInactive) name:UIApplicationWillResignActiveNotification object:nil];
24 | [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(becomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
25 | return [super init];
26 | }
27 | - (void)acceptConnection {
28 | NSError *error = nil;
29 | if (![server acceptOnPort:24865 error:&error]) {
30 | NSLog(@"error creating server: %@", error);
31 | }
32 | }
33 |
34 | - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
35 | @synchronized(connectedSockets)
36 | {
37 | [connectedSockets addObject:newSocket];
38 | }
39 | NSLog(@"got connection");
40 | // Welcome
41 | NSString *initResponse = @"W";
42 | NSData *initResp = [initResponse dataUsingEncoding:NSASCIIStringEncoding];
43 | [newSocket writeData:initResp withTimeout:-1 tag:0];
44 | [newSocket readDataToLength:1 withTimeout:5 tag:0];
45 | [self.viewController connected];
46 | }
47 | - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {}
48 | - (void)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length {
49 | switch (tag) {
50 | case 0:
51 | [sock readDataToLength:1 withTimeout:5 tag:0];
52 | break;
53 | default:
54 | [sock disconnect];
55 | break;
56 | }
57 | }
58 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
59 | switch (tag) {
60 | case 0: {
61 | switch (((uint8_t*)data.bytes)[0])
62 | {
63 | // Heartbeat Hello
64 | case 'H':
65 | [sock writeData:[@"H" dataUsingEncoding:NSASCIIStringEncoding] withTimeout:-1 tag:0];
66 | break;
67 | // Polling
68 | case 'P':
69 | [sock readDataToLength:1 withTimeout:1 tag:'P'];
70 | return;
71 | // LED
72 | case 'L':
73 | [sock readDataToLength:3 withTimeout:1 tag:'L'];
74 | return;
75 | // Unknown
76 | default:
77 | [sock disconnect];
78 | return;
79 | }
80 | break;
81 | }
82 | // Polling
83 | case 'P': {
84 | bool enabled = ((uint8_t*)data.bytes)[0];
85 | if (enabled) [self.viewController startPolling];
86 | else [self.viewController stopPolling];
87 | break;
88 | }
89 | // LED
90 | case 'L': {
91 | short r, g, b;
92 |
93 | r = ((uint8_t*)data.bytes)[0];
94 | g = ((uint8_t*)data.bytes)[1];
95 | b = ((uint8_t*)data.bytes)[2];
96 |
97 | [self.viewController updateLed:r :g :b];
98 | break;
99 | }
100 | }
101 | [sock readDataToLength:1 withTimeout:5 tag:0];
102 | }
103 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
104 | if (sock != server)
105 | {
106 | NSLog(@"connection ended");
107 | @synchronized(connectedSockets)
108 | {
109 | [connectedSockets removeObject:sock];
110 | if (connectedSockets.count == 0) {
111 | [self.viewController disconnected];
112 | }
113 | }
114 | }
115 | }
116 |
117 | -(void)BroadcastFeliCaData:(NSData*)data {
118 | NSString *header = [NSString stringWithFormat:@"CF%c", (char)(data.length)];
119 | NSMutableData *resp = [NSMutableData dataWithData:[header dataUsingEncoding:NSASCIIStringEncoding]];
120 | [resp appendData:data];
121 | [self BroadcastData:resp];
122 | }
123 |
124 | - (void)BroadcastData:(NSData*)data {
125 | for (GCDAsyncSocket* sock in connectedSockets) {
126 | [sock writeData:data withTimeout:-1 tag:0];
127 | }
128 | }
129 |
130 | - (void)becomeInactive {
131 | /*
132 | server.IPv4Enabled = NO;
133 | server.IPv6Enabled = NO;
134 | for (GCDAsyncSocket* sock in connectedSockets) {
135 | [sock disconnect];
136 | [connectedSockets removeObject:sock];
137 | }
138 | [server disconnect];
139 | */
140 | }
141 | - (void)becomeActive {
142 | /*
143 | server.IPv4Enabled = YES;
144 | server.IPv6Enabled = YES;
145 | [self acceptConnection];
146 | */
147 | }
148 |
149 | @end
150 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/AimeInterfaceProvider.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7523B2EB235D5D8B004A588C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7523B2EA235D5D8B004A588C /* AppDelegate.swift */; };
11 | 7523B2ED235D5D8B004A588C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7523B2EC235D5D8B004A588C /* SceneDelegate.swift */; };
12 | 7523B2EF235D5D8B004A588C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7523B2EE235D5D8B004A588C /* ViewController.swift */; };
13 | 7523B2F2235D5D8B004A588C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7523B2F0235D5D8B004A588C /* Main.storyboard */; };
14 | 7523B2F4235D5D8C004A588C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7523B2F3235D5D8C004A588C /* Assets.xcassets */; };
15 | 7523B2F7235D5D8C004A588C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7523B2F5235D5D8C004A588C /* LaunchScreen.storyboard */; };
16 | 7523B363236024A2004A588C /* CardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7523B362236024A2004A588C /* CardCell.swift */; };
17 | 7523B3652360302D004A588C /* CardTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7523B3642360302D004A588C /* CardTableViewController.swift */; };
18 | F3D817682D43A5C500233E1B /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D817672D43A5C500233E1B /* Data.swift */; };
19 | F3D8176C2D43A8A700233E1B /* SocketDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F3D8176B2D43A8A700233E1B /* SocketDelegate.m */; };
20 | F3D8176F2D43A92B00233E1B /* CocoaAsyncSocket in Frameworks */ = {isa = PBXBuildFile; productRef = F3D8176E2D43A92B00233E1B /* CocoaAsyncSocket */; };
21 | F6FB2B99235EEAE1005D0BEE /* FixedWidthInteger.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FB2B98235EEAE1005D0BEE /* FixedWidthInteger.swift */; };
22 | F6FB2B9C235EF00F005D0BEE /* FeliCaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FB2B9B235EF00F005D0BEE /* FeliCaReader.swift */; };
23 | F6FB2B9E235EF23F005D0BEE /* FeliCaReaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FB2B9D235EF23F005D0BEE /* FeliCaReaderDelegate.swift */; };
24 | F6FB2BA0235EF614005D0BEE /* FeliCaCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FB2B9F235EF614005D0BEE /* FeliCaCard.swift */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXFileReference section */
28 | 7523B2E7235D5D8B004A588C /* AimeInterfaceProvider.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AimeInterfaceProvider.app; sourceTree = BUILT_PRODUCTS_DIR; };
29 | 7523B2EA235D5D8B004A588C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
30 | 7523B2EC235D5D8B004A588C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
31 | 7523B2EE235D5D8B004A588C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
32 | 7523B2F1235D5D8B004A588C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
33 | 7523B2F3235D5D8C004A588C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
34 | 7523B2F6235D5D8C004A588C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
35 | 7523B2F8235D5D8C004A588C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
36 | 7523B31A235D5DA6004A588C /* AimeInterfaceProvider.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AimeInterfaceProvider.entitlements; sourceTree = ""; };
37 | 7523B362236024A2004A588C /* CardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardCell.swift; sourceTree = ""; };
38 | 7523B3642360302D004A588C /* CardTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardTableViewController.swift; sourceTree = ""; };
39 | F3D817672D43A5C500233E1B /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = ""; };
40 | F3D817692D43A8A600233E1B /* AimeInterfaceProvider-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AimeInterfaceProvider-Bridging-Header.h"; sourceTree = ""; };
41 | F3D8176A2D43A8A700233E1B /* SocketDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketDelegate.h; sourceTree = ""; };
42 | F3D8176B2D43A8A700233E1B /* SocketDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SocketDelegate.m; sourceTree = ""; };
43 | F6FB2B98235EEAE1005D0BEE /* FixedWidthInteger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FixedWidthInteger.swift; sourceTree = ""; };
44 | F6FB2B9B235EF00F005D0BEE /* FeliCaReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeliCaReader.swift; sourceTree = ""; };
45 | F6FB2B9D235EF23F005D0BEE /* FeliCaReaderDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeliCaReaderDelegate.swift; sourceTree = ""; };
46 | F6FB2B9F235EF614005D0BEE /* FeliCaCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeliCaCard.swift; sourceTree = ""; };
47 | /* End PBXFileReference section */
48 |
49 | /* Begin PBXFrameworksBuildPhase section */
50 | 7523B2E4235D5D8B004A588C /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | F3D8176F2D43A92B00233E1B /* CocoaAsyncSocket in Frameworks */,
55 | );
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | /* End PBXFrameworksBuildPhase section */
59 |
60 | /* Begin PBXGroup section */
61 | 7523B2DE235D5D8B004A588C = {
62 | isa = PBXGroup;
63 | children = (
64 | 7523B2E9235D5D8B004A588C /* AimeInterfaceProvider */,
65 | 7523B2E8235D5D8B004A588C /* Products */,
66 | );
67 | sourceTree = "";
68 | };
69 | 7523B2E8235D5D8B004A588C /* Products */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 7523B2E7235D5D8B004A588C /* AimeInterfaceProvider.app */,
73 | );
74 | name = Products;
75 | sourceTree = "";
76 | };
77 | 7523B2E9235D5D8B004A588C /* AimeInterfaceProvider */ = {
78 | isa = PBXGroup;
79 | children = (
80 | F6FB2B9A235EEFF1005D0BEE /* FeliCaReader */,
81 | F6FB2B97235EEACD005D0BEE /* Extension */,
82 | 7523B31A235D5DA6004A588C /* AimeInterfaceProvider.entitlements */,
83 | 7523B2EA235D5D8B004A588C /* AppDelegate.swift */,
84 | 7523B2EC235D5D8B004A588C /* SceneDelegate.swift */,
85 | 7523B2EE235D5D8B004A588C /* ViewController.swift */,
86 | F3D8176A2D43A8A700233E1B /* SocketDelegate.h */,
87 | F3D8176B2D43A8A700233E1B /* SocketDelegate.m */,
88 | 7523B2F0235D5D8B004A588C /* Main.storyboard */,
89 | 7523B2F3235D5D8C004A588C /* Assets.xcassets */,
90 | 7523B2F5235D5D8C004A588C /* LaunchScreen.storyboard */,
91 | 7523B2F8235D5D8C004A588C /* Info.plist */,
92 | 7523B362236024A2004A588C /* CardCell.swift */,
93 | 7523B3642360302D004A588C /* CardTableViewController.swift */,
94 | F3D817692D43A8A600233E1B /* AimeInterfaceProvider-Bridging-Header.h */,
95 | );
96 | path = AimeInterfaceProvider;
97 | sourceTree = "";
98 | };
99 | F6FB2B97235EEACD005D0BEE /* Extension */ = {
100 | isa = PBXGroup;
101 | children = (
102 | F6FB2B98235EEAE1005D0BEE /* FixedWidthInteger.swift */,
103 | F3D817672D43A5C500233E1B /* Data.swift */,
104 | );
105 | path = Extension;
106 | sourceTree = "";
107 | };
108 | F6FB2B9A235EEFF1005D0BEE /* FeliCaReader */ = {
109 | isa = PBXGroup;
110 | children = (
111 | F6FB2B9B235EF00F005D0BEE /* FeliCaReader.swift */,
112 | F6FB2B9D235EF23F005D0BEE /* FeliCaReaderDelegate.swift */,
113 | F6FB2B9F235EF614005D0BEE /* FeliCaCard.swift */,
114 | );
115 | path = FeliCaReader;
116 | sourceTree = "";
117 | };
118 | /* End PBXGroup section */
119 |
120 | /* Begin PBXNativeTarget section */
121 | 7523B2E6235D5D8B004A588C /* AimeInterfaceProvider */ = {
122 | isa = PBXNativeTarget;
123 | buildConfigurationList = 7523B311235D5D8D004A588C /* Build configuration list for PBXNativeTarget "AimeInterfaceProvider" */;
124 | buildPhases = (
125 | 7523B2E3235D5D8B004A588C /* Sources */,
126 | 7523B2E4235D5D8B004A588C /* Frameworks */,
127 | 7523B2E5235D5D8B004A588C /* Resources */,
128 | );
129 | buildRules = (
130 | );
131 | dependencies = (
132 | );
133 | name = AimeInterfaceProvider;
134 | packageProductDependencies = (
135 | F3D8176E2D43A92B00233E1B /* CocoaAsyncSocket */,
136 | );
137 | productName = nfc;
138 | productReference = 7523B2E7235D5D8B004A588C /* AimeInterfaceProvider.app */;
139 | productType = "com.apple.product-type.application";
140 | };
141 | /* End PBXNativeTarget section */
142 |
143 | /* Begin PBXProject section */
144 | 7523B2DF235D5D8B004A588C /* Project object */ = {
145 | isa = PBXProject;
146 | attributes = {
147 | LastSwiftUpdateCheck = 1100;
148 | LastUpgradeCheck = 1100;
149 | ORGANIZATIONNAME = kalan;
150 | TargetAttributes = {
151 | 7523B2E6235D5D8B004A588C = {
152 | CreatedOnToolsVersion = 11.0;
153 | LastSwiftMigration = 1540;
154 | };
155 | };
156 | };
157 | buildConfigurationList = 7523B2E2235D5D8B004A588C /* Build configuration list for PBXProject "AimeInterfaceProvider" */;
158 | compatibilityVersion = "Xcode 9.3";
159 | developmentRegion = en;
160 | hasScannedForEncodings = 0;
161 | knownRegions = (
162 | en,
163 | Base,
164 | );
165 | mainGroup = 7523B2DE235D5D8B004A588C;
166 | packageReferences = (
167 | F3D8176D2D43A92B00233E1B /* XCRemoteSwiftPackageReference "CocoaAsyncSocket" */,
168 | );
169 | productRefGroup = 7523B2E8235D5D8B004A588C /* Products */;
170 | projectDirPath = "";
171 | projectRoot = "";
172 | targets = (
173 | 7523B2E6235D5D8B004A588C /* AimeInterfaceProvider */,
174 | );
175 | };
176 | /* End PBXProject section */
177 |
178 | /* Begin PBXResourcesBuildPhase section */
179 | 7523B2E5235D5D8B004A588C /* Resources */ = {
180 | isa = PBXResourcesBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | 7523B2F7235D5D8C004A588C /* LaunchScreen.storyboard in Resources */,
184 | 7523B2F4235D5D8C004A588C /* Assets.xcassets in Resources */,
185 | 7523B2F2235D5D8B004A588C /* Main.storyboard in Resources */,
186 | );
187 | runOnlyForDeploymentPostprocessing = 0;
188 | };
189 | /* End PBXResourcesBuildPhase section */
190 |
191 | /* Begin PBXSourcesBuildPhase section */
192 | 7523B2E3235D5D8B004A588C /* Sources */ = {
193 | isa = PBXSourcesBuildPhase;
194 | buildActionMask = 2147483647;
195 | files = (
196 | F6FB2B9C235EF00F005D0BEE /* FeliCaReader.swift in Sources */,
197 | F3D817682D43A5C500233E1B /* Data.swift in Sources */,
198 | F6FB2BA0235EF614005D0BEE /* FeliCaCard.swift in Sources */,
199 | 7523B2EF235D5D8B004A588C /* ViewController.swift in Sources */,
200 | 7523B3652360302D004A588C /* CardTableViewController.swift in Sources */,
201 | F6FB2B99235EEAE1005D0BEE /* FixedWidthInteger.swift in Sources */,
202 | 7523B2EB235D5D8B004A588C /* AppDelegate.swift in Sources */,
203 | 7523B2ED235D5D8B004A588C /* SceneDelegate.swift in Sources */,
204 | F6FB2B9E235EF23F005D0BEE /* FeliCaReaderDelegate.swift in Sources */,
205 | 7523B363236024A2004A588C /* CardCell.swift in Sources */,
206 | F3D8176C2D43A8A700233E1B /* SocketDelegate.m in Sources */,
207 | );
208 | runOnlyForDeploymentPostprocessing = 0;
209 | };
210 | /* End PBXSourcesBuildPhase section */
211 |
212 | /* Begin PBXVariantGroup section */
213 | 7523B2F0235D5D8B004A588C /* Main.storyboard */ = {
214 | isa = PBXVariantGroup;
215 | children = (
216 | 7523B2F1235D5D8B004A588C /* Base */,
217 | );
218 | name = Main.storyboard;
219 | sourceTree = "";
220 | };
221 | 7523B2F5235D5D8C004A588C /* LaunchScreen.storyboard */ = {
222 | isa = PBXVariantGroup;
223 | children = (
224 | 7523B2F6235D5D8C004A588C /* Base */,
225 | );
226 | name = LaunchScreen.storyboard;
227 | sourceTree = "";
228 | };
229 | /* End PBXVariantGroup section */
230 |
231 | /* Begin XCBuildConfiguration section */
232 | 7523B30F235D5D8D004A588C /* Debug */ = {
233 | isa = XCBuildConfiguration;
234 | buildSettings = {
235 | ALWAYS_SEARCH_USER_PATHS = NO;
236 | CLANG_ANALYZER_NONNULL = YES;
237 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
238 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
239 | CLANG_CXX_LIBRARY = "libc++";
240 | CLANG_ENABLE_MODULES = YES;
241 | CLANG_ENABLE_OBJC_ARC = YES;
242 | CLANG_ENABLE_OBJC_WEAK = YES;
243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
244 | CLANG_WARN_BOOL_CONVERSION = YES;
245 | CLANG_WARN_COMMA = YES;
246 | CLANG_WARN_CONSTANT_CONVERSION = YES;
247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
249 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
250 | CLANG_WARN_EMPTY_BODY = YES;
251 | CLANG_WARN_ENUM_CONVERSION = YES;
252 | CLANG_WARN_INFINITE_RECURSION = YES;
253 | CLANG_WARN_INT_CONVERSION = YES;
254 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
255 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
256 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
257 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
258 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
259 | CLANG_WARN_STRICT_PROTOTYPES = YES;
260 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
261 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
262 | CLANG_WARN_UNREACHABLE_CODE = YES;
263 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
264 | COPY_PHASE_STRIP = NO;
265 | DEBUG_INFORMATION_FORMAT = dwarf;
266 | ENABLE_STRICT_OBJC_MSGSEND = YES;
267 | ENABLE_TESTABILITY = YES;
268 | GCC_C_LANGUAGE_STANDARD = gnu11;
269 | GCC_DYNAMIC_NO_PIC = NO;
270 | GCC_NO_COMMON_BLOCKS = YES;
271 | GCC_OPTIMIZATION_LEVEL = 0;
272 | GCC_PREPROCESSOR_DEFINITIONS = (
273 | "DEBUG=1",
274 | "$(inherited)",
275 | );
276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
277 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
278 | GCC_WARN_UNDECLARED_SELECTOR = YES;
279 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
280 | GCC_WARN_UNUSED_FUNCTION = YES;
281 | GCC_WARN_UNUSED_VARIABLE = YES;
282 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
283 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
284 | MTL_FAST_MATH = YES;
285 | ONLY_ACTIVE_ARCH = YES;
286 | SDKROOT = iphoneos;
287 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
288 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
289 | };
290 | name = Debug;
291 | };
292 | 7523B310235D5D8D004A588C /* Release */ = {
293 | isa = XCBuildConfiguration;
294 | buildSettings = {
295 | ALWAYS_SEARCH_USER_PATHS = NO;
296 | CLANG_ANALYZER_NONNULL = YES;
297 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
298 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
299 | CLANG_CXX_LIBRARY = "libc++";
300 | CLANG_ENABLE_MODULES = YES;
301 | CLANG_ENABLE_OBJC_ARC = YES;
302 | CLANG_ENABLE_OBJC_WEAK = YES;
303 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
304 | CLANG_WARN_BOOL_CONVERSION = YES;
305 | CLANG_WARN_COMMA = YES;
306 | CLANG_WARN_CONSTANT_CONVERSION = YES;
307 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
308 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
309 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
310 | CLANG_WARN_EMPTY_BODY = YES;
311 | CLANG_WARN_ENUM_CONVERSION = YES;
312 | CLANG_WARN_INFINITE_RECURSION = YES;
313 | CLANG_WARN_INT_CONVERSION = YES;
314 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
315 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
316 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
318 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
319 | CLANG_WARN_STRICT_PROTOTYPES = YES;
320 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
321 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
322 | CLANG_WARN_UNREACHABLE_CODE = YES;
323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
324 | COPY_PHASE_STRIP = NO;
325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
326 | ENABLE_NS_ASSERTIONS = NO;
327 | ENABLE_STRICT_OBJC_MSGSEND = YES;
328 | GCC_C_LANGUAGE_STANDARD = gnu11;
329 | GCC_NO_COMMON_BLOCKS = YES;
330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
332 | GCC_WARN_UNDECLARED_SELECTOR = YES;
333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
334 | GCC_WARN_UNUSED_FUNCTION = YES;
335 | GCC_WARN_UNUSED_VARIABLE = YES;
336 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
337 | MTL_ENABLE_DEBUG_INFO = NO;
338 | MTL_FAST_MATH = YES;
339 | SDKROOT = iphoneos;
340 | SWIFT_COMPILATION_MODE = wholemodule;
341 | SWIFT_OPTIMIZATION_LEVEL = "-O";
342 | VALIDATE_PRODUCT = YES;
343 | };
344 | name = Release;
345 | };
346 | 7523B312235D5D8D004A588C /* Debug */ = {
347 | isa = XCBuildConfiguration;
348 | buildSettings = {
349 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
350 | CLANG_ENABLE_MODULES = YES;
351 | CODE_SIGN_ENTITLEMENTS = AimeInterfaceProvider/AimeInterfaceProvider.entitlements;
352 | CODE_SIGN_STYLE = Automatic;
353 | CURRENT_PROJECT_VERSION = 1;
354 | DEVELOPMENT_TEAM = N7KMH3Y63U;
355 | INFOPLIST_FILE = AimeInterfaceProvider/Info.plist;
356 | INFOPLIST_KEY_CFBundleDisplayName = "Aime IO";
357 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
358 | LD_RUNPATH_SEARCH_PATHS = (
359 | "$(inherited)",
360 | "@executable_path/Frameworks",
361 | );
362 | MARKETING_VERSION = 0.1;
363 | PRODUCT_BUNDLE_IDENTIFIER = org.yyyr.aimeio;
364 | PRODUCT_NAME = "$(TARGET_NAME)";
365 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
366 | SUPPORTS_MACCATALYST = NO;
367 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
368 | SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
369 | SWIFT_OBJC_BRIDGING_HEADER = "AimeInterfaceProvider/AimeInterfaceProvider-Bridging-Header.h";
370 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
371 | SWIFT_VERSION = 5.0;
372 | TARGETED_DEVICE_FAMILY = 1;
373 | };
374 | name = Debug;
375 | };
376 | 7523B313235D5D8D004A588C /* Release */ = {
377 | isa = XCBuildConfiguration;
378 | buildSettings = {
379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
380 | CLANG_ENABLE_MODULES = YES;
381 | CODE_SIGN_ENTITLEMENTS = AimeInterfaceProvider/AimeInterfaceProvider.entitlements;
382 | CODE_SIGN_STYLE = Automatic;
383 | CURRENT_PROJECT_VERSION = 1;
384 | DEVELOPMENT_TEAM = N7KMH3Y63U;
385 | INFOPLIST_FILE = AimeInterfaceProvider/Info.plist;
386 | INFOPLIST_KEY_CFBundleDisplayName = "Aime IO";
387 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
388 | LD_RUNPATH_SEARCH_PATHS = (
389 | "$(inherited)",
390 | "@executable_path/Frameworks",
391 | );
392 | MARKETING_VERSION = 0.1;
393 | PRODUCT_BUNDLE_IDENTIFIER = org.yyyr.aimeio;
394 | PRODUCT_NAME = "$(TARGET_NAME)";
395 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
396 | SUPPORTS_MACCATALYST = NO;
397 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
398 | SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
399 | SWIFT_OBJC_BRIDGING_HEADER = "AimeInterfaceProvider/AimeInterfaceProvider-Bridging-Header.h";
400 | SWIFT_VERSION = 5.0;
401 | TARGETED_DEVICE_FAMILY = 1;
402 | };
403 | name = Release;
404 | };
405 | /* End XCBuildConfiguration section */
406 |
407 | /* Begin XCConfigurationList section */
408 | 7523B2E2235D5D8B004A588C /* Build configuration list for PBXProject "AimeInterfaceProvider" */ = {
409 | isa = XCConfigurationList;
410 | buildConfigurations = (
411 | 7523B30F235D5D8D004A588C /* Debug */,
412 | 7523B310235D5D8D004A588C /* Release */,
413 | );
414 | defaultConfigurationIsVisible = 0;
415 | defaultConfigurationName = Release;
416 | };
417 | 7523B311235D5D8D004A588C /* Build configuration list for PBXNativeTarget "AimeInterfaceProvider" */ = {
418 | isa = XCConfigurationList;
419 | buildConfigurations = (
420 | 7523B312235D5D8D004A588C /* Debug */,
421 | 7523B313235D5D8D004A588C /* Release */,
422 | );
423 | defaultConfigurationIsVisible = 0;
424 | defaultConfigurationName = Release;
425 | };
426 | /* End XCConfigurationList section */
427 |
428 | /* Begin XCRemoteSwiftPackageReference section */
429 | F3D8176D2D43A92B00233E1B /* XCRemoteSwiftPackageReference "CocoaAsyncSocket" */ = {
430 | isa = XCRemoteSwiftPackageReference;
431 | repositoryURL = "https://github.com/robbiehanson/CocoaAsyncSocket.git";
432 | requirement = {
433 | kind = upToNextMajorVersion;
434 | minimumVersion = 7.6.5;
435 | };
436 | };
437 | /* End XCRemoteSwiftPackageReference section */
438 |
439 | /* Begin XCSwiftPackageProductDependency section */
440 | F3D8176E2D43A92B00233E1B /* CocoaAsyncSocket */ = {
441 | isa = XCSwiftPackageProductDependency;
442 | package = F3D8176D2D43A92B00233E1B /* XCRemoteSwiftPackageReference "CocoaAsyncSocket" */;
443 | productName = CocoaAsyncSocket;
444 | };
445 | /* End XCSwiftPackageProductDependency section */
446 | };
447 | rootObject = 7523B2DF235D5D8B004A588C /* Project object */;
448 | }
449 |
--------------------------------------------------------------------------------