├── .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 | --------------------------------------------------------------------------------