chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

AppleにBroadcastの許可申請を出したら、もうちょい詳しく説明しろと言われる・・・→承認された

Echonet Lite搭載機器を探し出すプログラムを開発しようとして、Multicast送信のためには許可が必要と分かった。Apple Developperサイトから適当な申請を出したら機器間でどんなメッセージを送るのか説明しろと返事が来た。。EchonetLiteの仕様を知らないのだろうか。。EchonetLite機器って日本だけの流通??

Thank you for your interest in Multicast Networking. 
Can you please provide more details on which multicast 
or broadcast protocol (IP address and port) you need to
 use? What messages are exchanged between devices?

ちゃんと返事しないと、、こじれると厄介だ。。。
引き続き日本語で返事してもいいのやら。。

■追記(2020/12/13)
以下のような説明用のPDFを作成して、「ECHONET Liteプロトコルで機器情報をやり取りします」といった内容で回答した。どういう判断になるのやら。。

■追記(2020/12/19)
催促しようかどうしようかと思っていたら、承認のメールが来た。よかった。これでiPhoneアプリでEchonet Lite機器のスキャナーが作れる。。UDP Multicastが正しく実装できれば、だけど。

Your request to use Multicast Networking was approved. You can now add
 the Multicast Networking entitlement with your Provisioning Profile.

Instructions for using the entitlement are available and, for more information 
on using multicast, please read How to use multicast networking in your app. 
If you have questions or issues, please use the “Network” tag on the Apple 
Developer Forums.

嬉しかったので、へなちょこ英語でお礼を書いた。

早速、Apple DeveloperのID管理ページでMulticastを有効にする
f:id:chakoku:20201219140249p:plain:w300
XCodeとAppleDeveloperは同期処理をしているようで、AppleDeveloper側で有効にしつつXCode側でEntitlementを修正していないと、不一致が起きていると怒ってくる。com.apple.developer.networking.multicast についてはプルダウンメニューから選べないようなので、entitlementファイルを手で修正する。

権限のところでこじらせてしまい、これまでビルドしてたProjectを破棄して、あらたに作り直した。ビルドが通りUDP MulticastもExceptionを吐かずに正常動作するようになった。以下はXCodeのコンソール画面

2020-12-19 16:42:58.212195+0900 ELDeviceFinder[3577:516244] [] nw_listener_socket_inbox_create_socket IP_DROP_MEMBERSHIP 224.0.23.0:3610 failed [49: Can't assign requested address]
Group entered state waiting(POSIXErrorCode: Network is down)
waiting
POSIXErrorCode: Network is down
Group entered state ready
ready
send...UDP
Send complete with error nil
Received message from Optional(192.168.10.158:52652)
Optional(8 bytes)
Group entered state cancelled
cancelled
bye

PC側ではUDP MulticastのClienteを走らせていて、以下の通りiOSから配信されたパケットを受信することができた。

---------------
[68][65][6C][6C][6F][41][6C][6C]
---------------

技術的に一番やっかいなUDP Multicatは動かせるようになったので、、残る処理は、UDPパケットを正しいECHONET Liteパケットに直すのと、ECHONET Lite機器からの応答パケットを解析してリストに追加する処理だ。これはそれほどトラブルもなく実装できると思ってるのだが。。


EchonetLite仕様書
https://echonet.jp/wp/wp-content/uploads/pdf/General/Standard/ECHONET_lite_V1_12_jp/ECHONET-Lite_Ver.1.12_02.pdf



ESV:0x62 , EPC:0xD6
UDP Multicast Addr: 224.0.23.0 Port:3610

EchoneLite 機器を検出するアプリを開発・・・iOS上ではSwift Crash→申請が必要だった

理解不十分なまま、SwiftUIのプログラムと前回試作したUDP Multicastのプログラムを連結してiOS上で動かしてみた。すると、、ConnectionGroupのcancel()を呼んだ時点でcrashが発生。終了タイミングとか、資源解放の仕方とかが悪いのだろうか。。原因が分からず。

2020-12-09 20:38:26.284702+0900 ELDeviceFinder[6169:1234144] [] __nwlog_err_simulate_crash simulate crash already simulated "nw_connection_group_send_message_block_invoke called with null client_queue"
2020-12-09 20:38:26.285496+0900 ELDeviceFinder[6169:1234144] [] nw_connection_group_send_message_block_invoke called with null client_queue, dumping backtrace:

以下のような記事があった。理解がついていかない対策案なのだが。。
エラー:プロトコルが利用できない、バックトレースをダンプする

Developer Forumでも話題になっている(過去の記事だけど)
Odd network error/warning in lates… | Apple Developer Forums

■追記
さらに調べていると、LocalNetowrkでマルチキャストするアプリを作るには、アプリ用のIDにPermissionを設定する必要があることが分かった。LocalNetworkの利用はどんどん厳しくなっており、許可が必要らしいとは認識していたけど、プログラムのレベルでは有効化できないようである。知らなかった。。

Multicast Networking Entitlement Request から申請する必要あり
https://developer.apple.com/contact/request/networking-multicast

AppStoreのURLが必要なようで、AppStoreConnectにリリースのためのページを作成して、URLを決定した。なぜMulticastが必要かを説明する必要があり、「マルチキャストで機器を探し出すため」と日本語で理由を書きました。。


■参考記事、SwiftUI + Network
Naked Networking with SwiftUI. Network | by Mark Lucking | Medium

Multicastをするためにやるべきことの説明
iOS 14でローカルネットワークの利用 - Qiita
この記事のおかげで原因がわかりました。ありがたや。。

SwiftUIでForEachを使ってarrayをループ処理したい。。怒られる

SwiftUIを使って、Echonet Lite 機器をスキャンして、見つけ次第、リストに追加する実装を試みている。
以下が作成中のアプリの画面。scanの行の下に、検知デバイスをList形式で出したい。

が、、Stringを要素にもつArrayに対してForEachを使ってText()で追加しようとすると、ArrayはIdentifiableでないからダメと怒られる。ForEachで回す対象のデータ型はIDでアクセスできないとダメらしい(Identifiableプロトコルに準拠している必要があると理解)。Arrayもindexでアクセスしていると思うけど。。initを実行した時の要素数と、増減した時の要素数が違うから、配列のIndexは使えないということか??

List() {
     ForEach( 0..<deviceModel.data.count ){ index  in
           Text(deviceModel.data[index])
      }
}

以下がエラーメッセージ

ForEach<Range<Int>, Int, Text> count (4) != its initial count (1). 
`ForEach(_:content:)` should only be used for *constant* data. 
Instead conform data to `Identifiable` or use `ForEach(_:id:content:)` and 
provide an explicit `id`!

KeyPathを引数に加えてForEachのInit処理のエラーを回避させる方法が紹介されているけど、 \.self 表記でエラーが出る。(Swiftが古いから??)
もう一つの解法として、Arrayを使うのをやめて、Identifableな型を定義してそれを使って実装する記事が出ている。自分にはこっちの方が理解しやすい。だから、、新しい型を定義して、ID付きのデバイスリストを作って、ForEachに渡そうと思う。ただし、、新たに作った構造体を要素に持つ配列の宣言等、どうSwiftで書いたらいいのか、ちょっとすぐにわからないので、今日はここまで。。

■追記
先人のブログを参考に、デバイス管理配列をIdentifiableにして、idも付けた。ソースは以下

import Foundation

struct Device: Identifiable {
    var id: Int
    var name: String
}

class DeviceModel: ObservableObject {
    @Published var data:[Device] = [Device(id:0, name:"None")]
    var maxIndex:Int = 1
    var deviceService:DeviceService = DeviceService()
    init(){
        self.data[0].name = "ready to scan"
    }

モデル側はこのように改修して、ViewでForEachするとエラーが解消された。donguriさんに感謝。iOSアプリの表示は以下。ちょっとまだ細かい所はバグっているが、だいたいこんな感じで機器一覧が出たらいいなと。

残る作業は、UDPマルチキャストしてデバイスを探すコードの実装。

■ForEachのエラー回避方法
SwiftUIでいこう! - List,identifiable。|donguri|note
donguriさんによるIdentifiable化する解消案

Let's NoteでいつもWiFiが無効になる問題・・・原因は勝手にサービスを止めていたため→やっぱり治っておらず

古いLet's Note(CF-F10)を使っているが、電源Onの時や、Sleepからの復帰時WiFiが無効化された状態で立ち上がる問題があった。いろいろ調べたけど原因が分からなかった。昔排熱がうまくいかなくて、CPUクロックが落とされる症状があった時、負荷を軽くするため不要そうなサービスを片っ端から止めた時があった。その際、ネットワークサービスを立ち上げるためのサービス(起動サービスのようなものかと)も止めてしまったのでは?と思った。
そこで、サービス一覧から、ネットワークXXXというのを探してこれらを手動から自動起動に変更した。
下の画面が、手動→自動に戻したネットワーク関連のサービス群

すると、、Sleepから復帰した時WiFiが正しく立ち上がるようになった。いつもWireressのOff/Onをやり直してWiFiを復帰させていたけど、手間が減った。これは楽だ。

と思ったけど、、やっぱりまたWiFiが無効化になっていた。この程度の原因ではないようだ。はぁ。。

■ご参考URL
CF-F10用ドライバDLサイト
https://askpc.panasonic.co.jp/dl/install/f10a_64.html

https://jp.drvhub.net/devices/other-devices/wireless/switch-for-panasonic-pc

Swiftの言語仕様を学ぶ・・・型変換でstack trace... うーん。。。

「詳解Swift」という本を買って、サンプルを打ち込んで勉強中。今はデータ型を理解。。Swiftは型チェックが厳しく、また暗黙の型変換はなされない、ということで、型変換の関数(正確には関数ではなくイニシャライザらしい)が用意されている。Character型は1文字でString型は複数文字とのことで違いがよく分からない(なぜわざわざ1文字のCharacter型を作ったのか)(Cで言うところの、char / char[]の違いではなさそうだし)のだが、、分からないなりに無理やりString->Characterに変換させてみた。すると、、Fatal errorでスタックトレースが表示された。たしかに誤った操作でエラーかもしれないが、、、容易に発生しうる間違った型変換と思うのですが、スタックトレースしますかね。。それほど許せない操作なのか??

  7> Character("hello")
Fatal error: Can't form a Character from a String containing more than one extended grapheme cluster: file Swift/Character.swift, line 177
Current stack trace:
0    libswiftCore.so                    0x00007ffff7c21810 swift_reportError + 50
1    libswiftCore.so                    0x00007ffff7c95370 _swift_stdlib_reportFatalErrorInFile + 115
2    libswiftCore.so                    0x00007ffff797a16e <unavailable> + 1397102
3    libswiftCore.so                    0x00007ffff7979cc7 <unavailable> + 1395911
4    libswiftCore.so                    0x00007ffff79799a3 <unavailable> + 1395107
5    libswiftCore.so                    0x00007ffff7979410 _assertionFailure(_:_:file:line:flags:) + 511
6    libswiftCore.so                    0x00007ffff797989c <unavailable> + 1394844
7    libswiftCore.so                    0x00007ffff79873a0 Character.init(_:) + 290
Execution interrupted. Enter code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)

ちなみに、、動かしているのはMac上ではなく、WIndows上のUbuntuにswiftを入れてインタプリタモード(REPL)で動かしている。MAC OSだとこうはならないのだろうか。

■補足
勉強のため「詳解Swift」という本を買いました。本屋で「実践Swift」と読み比べたけど、どちらも同じような細かさの解説本と思いました。フォントのせいなのかレイアウトのせいなのか分かりませんが、ぱっと見た感じ、「詳解Swift」の方が読みやすいと思ったのでこちらを買いました。

詳解 Swift 第5版

詳解 Swift 第5版

確かにページ数も多いですが、基本的な説明と、メモリ管理、拡張(extention)、ジェネリクス等、高度な概念に分かれており、まず基本部分をざっと読めば最低のコードは組めるのではと期待*1。。章立てがうまくなされているので、基本仕様の解説を選んで、サンプルを打ち込みながら勉強することが可能。細かすぎて辞書のようにしか使えないということはありません。まだ少ししか読んでいませんが、筆者(萩原氏)の思いが伝わってくる本です。

■追記
少し勉強して分かったこと。swiftのソースコードを見ていると、頻繁に _ が出てくるけど、 _ は一体何なのかわからなった。 _ とは、使わない、指定しない、捨てる等、  を表すキーワードであった。
あと、文字列操作がめちゃくちゃめんどくさいことが分かった。 "abc"[3]のようなことは書けない、Stringの位置を指定するには、Index型を作って位置指定が必要であった。さらに、位置指定で取り出された結果はString型ではなくて、String.SubSequenc型であった。StringイニシャライザでString型に変換が必要らしかった。 勉強を兼ねてsubstringを書くと以下のようになると思う。もっと勉強すると、関数の冒頭でguardとか使えると思うが。

Swiftで書いた文字列抜き取り関数

func substring(_ str:String, _ start:Int, _ len:Int) -> String? {
   if start > (str.count - 1){
         return nil
   }
   if (start + len - 1) > (str.count - 1){
         return nil
   }
   let from = str.index(str.startIndex, offsetBy:start)
   let to = str.index(str.startIndex, offsetBy: start + len)
   let pick = String(str[from ..< to])
   return pick
}

prefixとsuffixを組み合わせたバージョン

func substring(_ str:String, _ start:Int, _ len:Int) -> String? {
   if start > (str.count - 1){
         return nil
   }
   if (start + len - 1) > (str.count - 1){
         return nil
   }
   let pick = str.suffix(str.count - start)      // 文字列末尾から切り取る
   return String(pick.prefix(len))                //文字列先頭から切り取る
}

Swiftは型にとことんこだわる言語ということで、気をぬいて実装するとすぐに型不一致で怒られるだろう。型を確認する関数を作った。

func showType<T>(_ tgt:T){
   print("type is",type(of: tgt))
}

■追記
クロージャを勉強。クロージャサンプルを作ってみる。。。UDP通信のコールバックはクロージャで表現されていると思う。多分。。

//クロージャ型変数を定義
var cat : (String, String) -> String

//クロージャを定義して変数に代入
cat = { "!!>>\($0), \($1)<<!!" }
print(cat("hello","bye"))         // クロージャを実行

//クロージャを引数とする関数を定義
func test(_ str1:String, _ str2:String, by clos:(String,String)->String) -> String {
  clos(str1, str2)
}

print(test("foo", "bar", by:cat))  // 関数を実行
print(test("aaa","bbb", by:{ "__\($0),\($1)__" }))

// 接尾クロージャ (trailing closure)で表現して実行
print(test("aaa","bbb"){ "_x_\($0),\($1)_x_" })

/*  
  output

!!>>hello, bye<<!!
!!>>foo, bar<<!!
__aaa,bbb__
_x_aaa,bbb_x_

*/

■追記
オプショナル型を学ぶ。nilを取りうる場合にoptional型を使い、値を使う時はxxx!によりラッピングを剥いて使うと理解。

//
//  option
//

func showType<T>(_ tgt:T){
   print("type is",type(of: tgt))
}

var x : Int?  // set nil to x
var y : Int   // set 0 to y

x = nil
y = 0

print("x = nil")
print("y = 0")
showType(x)
showType(y)

x = 0
y = 0

print("x = 0")
print("y = 0")
showType(x)
showType(y)


//print(y)
//if y > 0 { // ok
//   print(" y > 0 ")
//}
// x > 0 // Exception
//x!  //  Fatal error
//x+2 //  error

if x == nil {
  print("nil")
}else{
  print(x!)
}

print("-------------")
print("x = 1")
x = 1
if var xx  = x {
   showType(xx)
   xx = xx + 1
   print("u can use x, value:\(xx)") 
}else{
   showType(x)
   print("u can not use x") 
   print("x is.. \(String(describing:x))")
}

print("-------------")
print("x = nil")
x = nil
if var xx  = x {
   showType(xx)
   xx = xx + 1
   print("u can use x, value:\(xx)") 
}else{
   showType(x)
   print("u can not use x") 
   print("x is.. \(String(describing:x))") 
}
print("-------------")
print("x = 1")
x = 1
if var x  = x {
   showType(x)
   x = x + 1
   print("u can use x, value:\(x)") 
}else{
   showType(x)
   print("u can not use x") 
   print("x is.. \(String(describing:x))")
}

print("-------------")
print("x = nil")
x = nil
if var x  = x {
   showType(x)
   x = x + 1
   print("u can use x, value:\(x)") 
}else{
   showType(x)
   print("u can not use x") 
   print("x is.. \(String(describing:x))") 
}



x = nil
var val  = (x != nil) ? x! : -1
print(val)

// nilcoalescing operator ??
print("-----------------")
print("nil coalescing operator \"??\"")
val = x ?? -1
showType(val)
val += 1
print(val)


//
// IUO  implicitly unwrapped optional
//
print("-----------------")
print("IUO")
var xx : Int! = nil

xx = nil
if xx == nil {
  print("xx is nil")
  showType(xx)
  print(String(describing:xx))
}else{
  print("xx is not nil")
  xx += 1
  print(xx!)
}
xx = 1
if xx == nil {
  print("xx is nil")
  print(String(describing:xx))
}else{
  print("xx is not nil")
  showType(xx)
  xx += 1
  print(xx!)
}

/*********************************************:

x = nil
y = 0
type is Optional<Int>
type is Int
x = 0
y = 0
type is Optional<Int>
type is Int
0
-------------
x = 1
type is Int
u can use x, value:2
-------------
x = nil
type is Optional<Int>
u can not use x
x is.. nil
-------------
x = 1
type is Int
u can use x, value:2
-------------
x = nil
type is Optional<Int>
u can not use x
x is.. nil
-1
-----------------
nil coalescing operator "??"
type is Int
0
-----------------
IUO
xx is nil
type is Optional<Int>
nil
xx is not nil
type is Optional<Int>
2

**********************************************/

クラスの章をまったく読んでいないけど。。だんだん疲れてきたので、、文法はこれぐらいで、SwiftUIでPGしてみたい。

自分用メモ・・・プロトコルはswift全体にわたる基本概念だから読んだ方がいい

*1:オプショナル型だけはちゃんと理解する必要あり。

Swift Network Frameworkを使ってUDP Multicast通信を試す

iOSアプリ開発に向けて、Network Frameworkを使ってUDP Multicast通信をやってみる。細かい所はまだわかっていないけど、以下のコードで、WindowsでMulticastした電文の送受信までは動いた*1

import Network

guard let multicast = try? NWMulticastGroup(for:
    [ .hostPort(host: "224.0.23.0", port: 3610) ])
    else { fatalError("error in Muticast") }

let group = NWConnectionGroup(with: multicast, using: .udp)

group.setReceiveHandler(maximumMessageSize: 1024, rejectOversizedMessages: true) { (message, content, isComplete) in
    print("Received message from \(String(describing: message.remoteEndpoint))")

    //let sendContent = Data("ack".utf8)
    //message.reply(content: sendContent)
}
group.stateUpdateHandler = { (newState) in
    print("Group entered state \(String(describing: newState))")
}
let queue = DispatchQueue(label: "ExampleNetwork")
group.start(queue: queue)
//group.start(queue: .main)
sleep(10)

let str = "helloAll"
let groupSendContent = str.data(using: .utf8)
group.send(content: groupSendContent) { (error)  in
    print("Send complete with error \(String(describing: error))")
}
group.cancel()
print("bye")

実行結果の表示

Group entered state waiting(POSIXErrorCode: Network is down)
Group entered state ready                                                   // ・・状態がReadyに遷移
Received message from Optional(192.168.10.155:62725)   // ・・・送信しているWindows側IP
Received message from Optional(192.168.10.155:62726)
Send complete with error nil
Received message from Optional(192.168.10.161:50947)   // ・・・Multicastした自分自身のIP
Received message from Optional(192.168.10.155:62727)
bye
Group entered state cancelled                                            // ・・状態がCancelledに遷移

ネットワークの状態がReadyに遷移したタイミングでUDPマルチキャストを投げるように修正
受信データを表示させたいが、型変換がよくわからずWarningになっている。
Swiftの基本仕様がわかっていない。。

import Network

guard let multicast = try? NWMulticastGroup(for:
    [ .hostPort(host: "224.0.23.0", port: 3610) ])
    else { fatalError("error in Muticast") }

let group = NWConnectionGroup(with: multicast, using: .udp)

group.setReceiveHandler(maximumMessageSize: 1024, rejectOversizedMessages: true) { (message, content, isComplete) in
    print("Received message from \(String(describing: message.remoteEndpoint))")
    //let message = String(data: content, encoding: .utf8)
    //let message = Data(content, encoding: .utf8)
    print(content)
    //let sendContent = Data("ack".utf8)
    //message.reply(content: sendContent)
}
group.stateUpdateHandler = { (newState) in
    print("Group entered state \(String(describing: newState))")
    switch newState {
    case .ready:
        print("ready")
        let str = "helloAll"
        let groupSendContent = str.data(using: .utf8)
        group.send(content: groupSendContent) { (error)  in
            print("Send complete with error \(String(describing: error))")
        }
    case .waiting(let error):
        print("waiting")
        print(error)
    case .setup:
        print("setup")
    case .cancelled:
        print("cancelled")
    case .failed:
        print("failed")
    //case .preparing:
    //    print("preparing")
    default:
        print("default")
    }
}
let queue = DispatchQueue(label: "ExampleNetwork")
group.start(queue: queue)
//group.start(queue: .main)
sleep(5)
group.cancel()
print("bye")

■参考にした記事
Swiftでコマンドラインツール作成の誘い - Qiita

*1:受信データの内容は未確認

Swiftをコマンドラインから起動する->実行できたがハングした

UPDのテストプログラム等をXCodeからビルドするのは手間なので、コマンドラインでさくっと動かせると楽。
普通に実行させると以下のようなエラーになる。

$ swift test.swift 
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools),
 missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

調べると、設定が必要なようであった。

sudo xcode-select -s /Applications/Xcode.app
sudo xcode-select --install

結果、以下のようにコマンドラインから実行可能となった。

$ cat test.swift
#!/usr/bin/swift

print("Hello World")

$ swift test.swift
Hello World

$ ./test.swift 
Hello World

他人のサンプルを少し編集して実行(文法的におかしなところはあるにせよ)

import Network

//let host = NWEndpoint.Host(ipFamily.ssdpGroupName)
let multicastGroup = try NWMulticastGroup(for: [.hostPort(host: "192.168.10.120", port: .ssdp)])
let ssdpGroup = NWConnectionGroup(with: multicastGroup, using: .udp)
ssdpGroup.stateUpdateHandler = { newState in
                             print("Reached new state: \(newState)")
}
ssdpGroup.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: false, handler: {[weak\
 self] (message, content, isComplete) in
                                        	print("SSDP message received, do something here...")
})

let queue = DispatchQueue(label: "ExampleNetwork")
ssdpGroup.start(queue: queue)

NWMulticastGroup等が不明と言って怒られる。なぜだ?

$ swift UDP_mul_sample.swift 
UDP_mul_sample.swift:4:26: error: use of unresolved identifier 'NWMulticastGroup'
let multicastGroup = try NWMulticastGroup(for: [.hostPort(host: "192.168.10.120", port: .ssdp)])
                         ^~~~~~~~~~~~~~~~
UDP_mul_sample.swift:5:17: error: use of unresolved identifier 'NWConnectionGroup'
let ssdpGroup = NWConnectionGroup(with: multicastGroup, using: .udp)
                ^~~~~~~~~~~~~~~~~
UDP_mul_sample.swift:9:104: error: use of unresolved identifier 'self'

コマンドラインから実行しているのが悪いのか?それとも、実行しているOSのバージョンがMojaveだから?? catalinaに上げないとUDP Multicastは使えない?? 自分のMACに入っているFrameworkが古いせい??

少し調べた結果、iOSのバージョンを14.0、 XCodeのバージョンを12.0以上に上げる必要があるようだった。幸い、新しいOSのMacBookを借りられたので実行してみた。以下はソースコード(Swiftの細かい仕様は不勉強でわからんです)

import Network

//let host = NWEndpoint.Host(ipFamily.ssdpGroupName)
let multicastGroup = try NWMulticastGroup(for: [.hostPort(host: "192.168.10.120", port: 1234)])
let ssdpGroup = NWConnectionGroup(with: multicastGroup, using: .udp)
ssdpGroup.stateUpdateHandler = { newState in
                             print("Reached new state: \(newState)")
}
ssdpGroup.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: false, handler: {
(message, content, isComplete) in
         	print("SSDP message received, do something here...")
})

let queue = DispatchQueue(label: "ExampleNetwork")
ssdpGroup.start(queue: queue)

エラーは発生しなかったが、思いっきりハングした。Exceptionすら吐いてないのでは?? SwiftはExceptionを吐かずにダンプするのか。。命令違反と怒られてもな。。SwiftはLLVM上で動いているのか。。XCodeのPlayGroundで走らせるとどうなるんだろう。。やっぱりダンプを吐くのだろうか。。

 % swift test2.swift
Stack dump:
0.	Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret test2.swift -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -color-diagnostics -target-sdk-version 11.0 -module-name test2 
1.	Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8)
2.	While running user code "test2.swift"
0  swift                    0x000000010f555c15 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1  swift                    0x000000010f556332 SignalHandler(int) + 610
2  libsystem_platform.dylib 0x00007fff20363d7d _sigtramp + 29
3  libsystem_platform.dylib 0x00007f855ff0ffff _sigtramp + 18446743550792745631
4  libswiftNetwork.dylib    0x00007fff54fcde07 $s7Network17NWConnectionGroupC4with5usingAcA17NWGroupDescriptor_p_AA12NWParametersCtcfC + 55
5  libswiftNetwork.dylib    0x000000011432120f $s7Network17NWConnectionGroupC4with5usingAcA17NWGroupDescriptor_p_AA12NWParametersCtcfC + 18446603343724098623
6  swift                    0x000000010adb4605 llvm::orc::runAsMain(int (*)(int, char**), llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, llvm::Optional<llvm::StringRef>) + 1221
7  swift                    0x000000010ad91ebb swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions const&, swift::SILOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >&&) + 6763
8  swift                    0x000000010ad6d5ce performCompileStepsPostSILGen(swift::CompilerInstance&, swift::CompilerInvocation const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 2446
9  swift                    0x000000010ad5d7ba swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 21802
10 swift                    0x000000010acde2c1 main + 1265
11 libdyld.dylib            0x00007fff2033a631 start + 1
zsh: illegal hardware instruction  swift test2.swift

今後の取り組み
(1)どこでハングしているのかもわからないので、ソースコードを減らしながら落ちている原因のコードを探す
(2)Apppleから手取り足取りでNetwork FrameworkのUDPサンプルコードが出ているのでそっちのコードを打ち込んでみる


■参考URL
コマンドラインから実行するためのセットアップ
https://qiita.com/KanikaniYou/items/9829eef54b2e0d300de1