LoginSignup
4
7

More than 5 years have passed since last update.

[swift]モールス信号をiPhone/iPadのフラッシュで行ってみる

Posted at

はじめに

ふとモールス信号の仕組みってどうなっているんだ?と思ったのでモールス信号を発光するアプリを作ってみた
途中からめんどくさくなってかなりソースコードが汚くなっていますがご了承ください

ソースコード

EnumEnumerable.swift

import Foundation

public protocol EnumEnumerable {
    associatedtype Case = Self
    static var dict: [String:String] {get}
}

public extension EnumEnumerable where Case: Hashable {
    private static var iterator: AnyIterator<Case> {
        var n = 0
        return AnyIterator {
            defer { n += 1 }

            let next = withUnsafePointer(to: &n) {
                UnsafeRawPointer($0).assumingMemoryBound(to: Case.self).pointee
            }
            return next.hashValue == n ? next : nil
        }
    }

    public static func enumerate() -> EnumeratedSequence<AnySequence<Case>> {
        return AnySequence(self.iterator).enumerated()
    }

    public static var cases: [Case] {
        return Array(self.iterator)
    }


    public static var count: Int {
        return self.cases.count
    }
}

Morse.swift


protocol Morse {
    static func patern(original: String) -> String
}

WesternMorse.swift

enum WesternMorse: String, Morse, EnumEnumerable {
    case A = "・-"
    case B = "-・・・"
    case C = "-・-・"
    case D = "-・・"
    case E = "・"
    case F = "・・-・"
    case G = "--・"
    case H = "・・・・"
    case I = "・・"
    case J = "・---"
    case K = "-・-"
    case L = "・-・・"
    case M = "--"
    case N = "-・"
    case O = "---"
    case P = "・--・"
    case Q = "--・-"
    case R = "・-・"
    case S = "・・・"
    case T = "-"
    case U = "・・-"
    case V = "・・・-"
    case W = "・--"
    case X = "-・・-"
    case Y = "-・--"
    case Z = "--・・"
    //数字
    case one = "・----"
    case two = "・・---"
    case three = "・・・--"
    case four = "・・・・-"
    case five = "・・・・・"
    case six = "-・・・・"
    case seven = "--・・・"
    case eight = "---・・"
    case nine = "----・"
    case zero = "-----"
    //記号
    case question = "・・--・・"
    case exclamation = "-・-・--"
    case period = "・-・-・-"
    case comma = "--・・--"
    case hyphen = "-・・・・-"
    case blank = "____"
    case delimiter = "___"


    public static var dict: [String:String] {
        var value = [String: String]()
        for var k in self.cases{
            value["\(k)"] = "\(k.rawValue)"
        }
        return value
    }

    static func patern(original: String) -> String {
        var returnValue = ""
        for char in original.characters {
            let charStr = transformation((String(char).uppercased()))
            returnValue += self.dict["\(charStr)"]! + self.dict["delimiter"]!
        }
        return returnValue
    }

    private static func transformation(_ char: String) -> String {
        let numArray = ["zero","one","two","three","four","five","six","seven","eight","nine"]
        if char.isNumber() {
            return numArray[Int(char)!]
        }
        switch char {
        case "!":
            return "exclamation"
        case "?":
            return "question"
        case ",":
            return "comma"
        case ".":
            return "period"
        case "-":
            return "hyphen"
        case " "," ":
            return "blank"
        default:
            return char
        }
    }
}

MorseSignalDevice.swift

protocol MorseSignalDevice {
    func device() -> AVCaptureDevice
}

enum morseSignalDevice : MorseSignalDevice{
    case torch
    func device() -> AVCaptureDevice {
        switch self {
        case .torch:
            let avDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
            guard let device = avDevice else {
                return AVCaptureDevice()
            }
            return device            
        }
    }
}

MorseSignal.swift

import Foundation
import AVFoundation


protocol MorseSignal {
    static func outSignal(signal: String, device: AVCaptureDevice)
}

public enum torchHandler: MorseSignal{
    public static func outSignal(signal: String, device: AVCaptureDevice){
        do {
            try device.lockForConfiguration()
        } catch {
            return
        }
        let sleepTime: useconds_t = 100000
        for char in signal.characters {
            switch String(char) {
            case "・":
                device.torchMode = .on
                usleep(sleepTime)
                device.torchMode = .off
            case "-":
                device.torchMode = .on
                usleep(sleepTime*3)
                device.torchMode = .off
            case "_":
                device.torchMode = .off
                usleep(sleepTime)
            default:
                usleep(0)
            }
        }
        device.unlockForConfiguration()

    }

}

ViewController.swift

使うときは以下のようにするとできます


@IBAction func pushMorseSignal(_ sender: Any) {
        let signal = WesternMorse.patern(original: textField.text!)
        let device = morseSignalDevice.torch.device()
        if device.hasTorch {

            torchHandler.outSignal(signal: signal, device: device)
        }
}

String+.swift

import Foundation

extension String {
    func isNumber() -> Bool {
        let predicate = NSPredicate(format: "SELF MATCHES '\\\\d+'")
        return predicate.evaluate(with: self)
    }

}

作ってみて

和文モールスもcaseだけは書いたんですが力尽きました
ただひたすらcase文とモールス信号パターンを打つのがめんどくさかったです

参考

iPhoneのLEDライトをLピカさせよう!

Swift3.0版、Enumのcaseを配列で返すProtocol Extension

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7