haruzira_sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,799 @@
1
+ #!/usr/bin/ruby
2
+ # -*- coding: utf-8 -*-
3
+ require "socket"
4
+ require "thread"
5
+ require "timeout"
6
+ require "haruzira_sdk/HaruziraRequire"
7
+ #require "./HaruziraRequire"
8
+ #require "./HzTrace"
9
+
10
+ #region enum
11
+ # <summary>
12
+ # Mode of Text Speech
13
+ # </summary>
14
+ module HzSpeechTextMode
15
+ Text = 0x00 #テキスト
16
+ Ssml = 0x01 #SSML
17
+ end
18
+
19
+ # <summary>
20
+ # Priority of Speech
21
+ # </summary>
22
+ module HzSpeechLevel
23
+ Low = 0x00 #低い(読み上げない)
24
+ Normal = 0x01 #通常(順次読み上げ)
25
+ High = 0x02 #高い(割り込み読み上げ)
26
+ end
27
+
28
+ # <summary>
29
+ # Gender of Speecher
30
+ # </summary>
31
+ module HzSpeechGender
32
+ Female = 0x00 #女性
33
+ Male = 0x01 #男性
34
+ Neutral = 0x02 #中性
35
+ end
36
+ #endregion
37
+
38
+ class ClientTcpCommunication
39
+
40
+ # <summary>
41
+ # Construct
42
+ # </summary>
43
+ def initialize()
44
+ #region 変数・定数
45
+ @DISCONNECT_REASON_END = 0x10; #通信終了通知送信時
46
+ @DISCONNECT_REASON_CANCEL = 0x11 #キャンセル発生時
47
+ @DISCONNECT_REASON_SERVER_IREGULAR = 0x12 #サーバー側でイレギュラー障害発生
48
+ @DISCONNECT_REASON_CLIENT_IREGULAR = 0x13; #クライアント側でイレギュラー障害発生
49
+ @QUEUE_RECEIVED = "OK"
50
+
51
+ @encryption = Encryption.new
52
+ #@encryption = nil
53
+
54
+ @work_rcv = nil #メッセージ受信スレッド
55
+ @listenTask = nil #非同期メッセージ受信メインスレッド
56
+ @tcpSvr = nil #TCPServer
57
+ @ackStartCommAutoResetEvent = Queue.new
58
+ @ackSendSpeechDataAutoResetEvent = Queue.new
59
+ @cltSocket = nil
60
+ @ServerPortNo = 46000
61
+ @ServerIP = "127.0.0.1"
62
+ @ReceivePort = 46100
63
+ @ReqSendDataText = ""
64
+ @ReqSendDataEncrypt = false
65
+ @ReqSendDataEncryptKey = ""
66
+ @ReqSendDataAccountName = ""
67
+ @ReqSendDataPasswd = ""
68
+ @ReqSendDataSpeechMode = HzSpeechTextMode::Text
69
+ @ReqSendDataSpeechLevel = HzSpeechLevel::Normal
70
+ @ReqSendDataSpeechLocaleId = 0x0411
71
+ @ReqSendDataSpeechGender = HzSpeechGender::Neutral
72
+ @ReqSendDataSpeechAge = 25
73
+ @ReqSendDataSpeechRepeat = 0
74
+ @SendDataHexStr = ""
75
+ @SendDataLength = 0
76
+ @ReceiveStatus = 0x00
77
+ @ReceiveAckTimeOut = RECEIVE_TIME_OUT
78
+
79
+ #メッセージ受信時イベント定義
80
+ @EvNotifyCompeteReading = nil #読み上げ完了通知受信時イベント
81
+ @EvNotifyMessageEvent = nil #Exception発生時イベント(切断以外)
82
+ @EvNotifyReceivedDisConnectEvent = nil #切断発生時イベント(サーバー側からの切断など)
83
+ #endregion
84
+ end
85
+
86
+ #define accessor
87
+ attr_accessor :ServerPortNo, :ServerIP, :ReceivePort, :ReqSendDataText, :ReqSendDataEncrypt, :ReqSendDataEncryptKey, :ReqSendDataAccountName, :ReqSendDataPasswd, \
88
+ :ReqSendDataSpeechMode, :ReqSendDataSpeechLevel, :ReqSendDataSpeechLocaleId, :ReqSendDataSpeechGender, :ReqSendDataSpeechAge, :ReqSendDataSpeechRepeat, \
89
+ :EvNotifyCompeteReading, :EvNotifyMessageEvent, :EvNotifyReceivedDisConnectEvent
90
+ attr_reader :SendDataHexStr, :SendDataLength, :ReceiveStatus
91
+
92
+ #region イベントコールバック関数ラッパー
93
+ def evNotifyMessageEvent(msg, msg_id, err_code)
94
+ if(@EvNotifyMessageEvent != nil)
95
+ @EvNotifyMessageEvent.call(msg, msg_id, err_code)
96
+ end
97
+ end
98
+
99
+ def evNotifyReceivedDisConnectEvent(msg, status)
100
+ if (@EvNotifyReceivedDisConnectEvent != nil)
101
+ @EvNotifyReceivedDisConnectEvent.call(msg, status);
102
+ end
103
+ end
104
+
105
+ def evNotifyCompeteReading(result, time_stamp)
106
+ if (@EvNotifyCompeteReading != nil)
107
+ @EvNotifyCompeteReading.call(result, time_stamp);
108
+ end
109
+ end
110
+ #endregion
111
+
112
+ # <summary>
113
+ # トレース出力設定
114
+ # </summary>
115
+ # <returns></returns>
116
+ def setTraceOutPut(val)
117
+ HzTrace.setTraceOutPut(val)
118
+ end
119
+
120
+ # <summary>
121
+ # 応答受信時タイムアウト取得・設定
122
+ # </summary>
123
+ # <param name="value">タイムアウト値</param>
124
+ def receiveAckTimeOut(value = nil)
125
+ if(value == nil)
126
+ #Get
127
+ return @ReceiveAckTimeOut
128
+ else
129
+ #Set
130
+ if(value > RECEIVE_MAX_TIME_OUT)
131
+ @ReceiveAckTimeOut = RECEIVE_MAX_TIME_OUT
132
+ elsif(value < RECEIVE_MIN_TIME_OUT)
133
+ @ReceiveAckTimeOut = RECEIVE_MIN_TIME_OUT
134
+ else
135
+ @ReceiveAckTimeOut = value
136
+ end
137
+ end
138
+ end
139
+
140
+ # <summary>
141
+ # 非同期メッセージ受信用リスナータスク
142
+ # </summary>
143
+ # <returns></returns>
144
+ def listenerTask()
145
+ Thread.abort_on_exception = true
146
+ begin
147
+ TCPServer.open("0.0.0.0", @ReceivePort) do |svr|
148
+ HzTrace.traceCommMessage("非同期メッセージ受信スレッド開始")
149
+ loop do
150
+ @tcpSvr = Thread.start(svr.accept) do |svr_sock|
151
+ rcvLen = 0
152
+ rcvBuf = nil
153
+ reqStartComm = MsgReqStartComm.new
154
+ ackSendSpeechData = MsgAckSendSpeechData.new
155
+ ackStartComm = MsgAckStartComm.new
156
+ notifyEndComm = MsgNotifyEndComm.new
157
+ #notifyControlCommand = MsgNotifyControlCommand.new
158
+ notifyStopComm = MsgNotifyStopComm.new
159
+ notifyCompleteReading = MsgNotifyCompleteSpeech.new
160
+ rcvEndFlg = false
161
+ @ReceiveStatus = notifyStopComm.REASON_CODE_NONE #切断発生時ステータス
162
+
163
+ begin
164
+ #サーバーからの送信メッセージをチェック
165
+ loop do
166
+ rcvEndFlg = false
167
+ rcvLen = 0
168
+ if(rcvBuf != nil)
169
+ rcvBuf.clear
170
+ end
171
+
172
+ begin
173
+ if (svr_sock != nil)
174
+ #rcvLen = await _cltStream.ReadAsync(rcvBuf, 0, rcvBuf.Length)
175
+ rcvBuf = svr_sock.readpartial(SEND_READ_DATA_MAX_SIZE)
176
+ #rcvBuf = rcvBuf.delete("[] ").split(',').map(&:to_i)
177
+ rcvBuf = rcvBuf.unpack("C*")
178
+ rcvLen = rcvBuf.length
179
+ #p rcvBuf
180
+
181
+ #puts("【CL】接続先からデータを受信しました。: Data Size[#{rcvLen}]")
182
+ HzTrace.traceCommMessage("【CL】接続先からデータを受信しました。: Data Size[%d]" % [rcvLen])
183
+ if (rcvLen <= 0)
184
+ puts("受信データを取得できないため、接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
185
+ @ReceiveStatus = DISCONNECT_REASON_SERVER_IREGULAR
186
+ raise("受信データを取得できないため、接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
187
+ #elsif (@ctsClient.IsCancellationRequested)
188
+ # @ReceiveStatus = @DISCONNECT_REASON_CANCEL
189
+ # raise("キャンセルリクエストが発生しました。接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
190
+ end
191
+
192
+ else
193
+ @ReceiveStatus = @DISCONNECT_REASON_CLIENT_IREGULAR
194
+ raise("受信データを取得できないため、接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
195
+ end
196
+
197
+ rescue Exception => ex
198
+ #タイムアウト時はWait
199
+ if(!ex.to_s.include?("end of file"))
200
+ puts("【CL listener】接続先からのデータ受信エラー:%s}" % [ex])
201
+ raise(ex)
202
+ end
203
+ #next
204
+ end
205
+
206
+ #受信データ解析
207
+ if (rcvLen > 0)
208
+ case rcvBuf[0]
209
+ when MSG_NOTIFY_COMPLETE_SPEECH
210
+ if (rcvLen != notifyCompleteReading.total_len)
211
+ #受信データサイズが不正
212
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
213
+ raise("不正なデータを受信したため、接続先から切断します。\r\nnメッセージID[0x%02x], 受信サイズ[%d]" % [notifyCompleteReading.id, rcvLen])
214
+ end
215
+ notifyCompleteReading.result = rcvBuf[notifyCompleteReading.INDEX_RESULT]
216
+ notifyCompleteReading.time_stamp = rcvBuf[notifyCompleteReading.INDEX_TIME_STAMP..(notifyCompleteReading.INDEX_TIME_STAMP + 7)]
217
+ HzTrace.traceCommMessage("【CL】読み上げ完了通知受信(0x%02x):Result[0x%02x], TimeStamp[%s]" % [notifyCompleteReading.id, notifyCompleteReading.result, notifyCompleteReading.time_stamp.pack("C*")])
218
+ #コールバック関数呼び出し
219
+ evNotifyCompeteReading(notifyCompleteReading.result, notifyCompleteReading.time_stamp.pack("C*"))
220
+ when MSG_NOTIFY_STOP_COMM
221
+ if (rcvLen != notifyStopComm.total_len)
222
+ #受信データサイズが不正
223
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
224
+ raise("不正なデータを受信したため、接続先から切断します。\r\nメッセージID[{0:x2}], 受信サイズ[{1}]", notifyStopComm.id, rcvLen)
225
+ end
226
+ notifyStopComm.stop_code = rcvBuf[notifyStopComm.INDEX_STOP_CODE]
227
+ @ReceiveStatus = notifyStopComm.reason_code
228
+ HzTrace.traceCommMessage("【CL】通信停止通知受信(0x%02x):Stop Code[0x%02x], Reason Code[0x%02x]" % [notifyStopComm.id, notifyStopComm.stop_code, notifyStopComm.reason_code])
229
+ evNotifyReceivedDisConnectEvent(("クライアント: " + "接続先から通信停止通知を受信しました。接続先から切断します。\r\nメッセージID[0x%02x], 停止コード[0x%02x], 理由コード[0x%02x]" % [notifyStopComm.id, notifyStopComm.stop_code, notifyStopComm.reason_code]), @ReceiveStatus)
230
+ rcvEndFlg = true
231
+ else
232
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
233
+ raise("不正なデータを受信しました。Message ID[0x%02x], 受信サイズ[%d]", rcvBuf[0], rcvLen)
234
+
235
+ end #case
236
+ if (rcvEndFlg)
237
+ break
238
+ end
239
+ end #if(rcvLen > 0)
240
+
241
+
242
+ end #loop do
243
+
244
+ rescue Exception => ex
245
+ evNotifyReceivedDisConnectEvent("非同期メッセージ受信スレッド: %s" % [ex], @ReceiveStatus)
246
+ #if (ex.HResult != HaruZiraMessage.HRSEULT_SOCKET_CLOSED)
247
+ # #notifyEndCommProc()
248
+ # evNotifyReceivedDisConnectEvent("受信スレッド: " + ex.Message, @ReceiveStatus)
249
+ #end
250
+ ensure
251
+ if (svr_sock != nil)
252
+ svr_sock.close()
253
+ svr_sock = nil
254
+ end
255
+ end
256
+ end #Thread
257
+ end#loop
258
+ end #TCPServer
259
+ rescue Exception => ex
260
+ if(@ReceiveStatus == 0x00)
261
+ @ReceiveStatus = @DISCONNECT_REASON_CLIENT_IREGULAR
262
+ end
263
+ @ackSendSpeechDataAutoResetEvent.push(@QUEUE_RECEIVED)
264
+ evNotifyReceivedDisConnectEvent("非同期メッセージ受信スレッド: %s" % [ex], @ReceiveStatus)
265
+ ensure
266
+ if(@listenTask != nil)
267
+ @listenTask = nil
268
+ end
269
+ end
270
+ HzTrace.traceCommMessage("非同期メッセージ受信スレッド終了")
271
+
272
+ end #def
273
+
274
+
275
+ # <summary>
276
+ # 受信ワーカータスク
277
+ # </summary>
278
+ # <returns></returns>
279
+ def receiveWorker()
280
+ Thread.abort_on_exception = true
281
+ @work_rcv = Thread.start do
282
+ rcvLen = 0
283
+ rcvBuf = nil
284
+ reqStartComm = MsgReqStartComm.new
285
+ ackSendSpeechData = MsgAckSendSpeechData.new
286
+ ackStartComm = MsgAckStartComm.new
287
+ notifyEndComm = MsgNotifyEndComm.new
288
+ #notifyControlCommand = MsgNotifyControlCommand.new
289
+ notifyStopComm = MsgNotifyStopComm.new
290
+ notifyCompleteReading = MsgNotifyCompleteSpeech.new
291
+ rcvEndFlg = false
292
+ @ReceiveStatus = notifyStopComm.REASON_CODE_NONE #切断発生時ステータス
293
+
294
+ begin
295
+ HzTrace.traceCommMessage("受信ワーカースレッド開始")
296
+ #サーバーからの送信メッセージをチェック
297
+ loop do
298
+ rcvEndFlg = false
299
+ rcvLen = 0
300
+ @ReceiveStatus = 0x00
301
+ if(rcvBuf != nil)
302
+ rcvBuf.clear
303
+ end
304
+
305
+ begin
306
+ if (@cltSocket != nil)
307
+ #rcvLen = await _cltStream.ReadAsync(rcvBuf, 0, rcvBuf.Length)
308
+ rcvBuf = @cltSocket.readpartial(SEND_READ_DATA_MAX_SIZE)
309
+ #rcvBuf = rcvBuf.delete("[] ").split(',').map(&:to_i)
310
+ rcvBuf = rcvBuf.unpack("C*")
311
+ rcvLen = rcvBuf.length
312
+ #p rcvBuf
313
+
314
+ #puts("【CL】接続先からデータを受信しました。: Data Size[#{rcvLen}]")
315
+ HzTrace.traceCommMessage("【CL】接続先からデータを受信しました。: Data Size[%d]" % [rcvLen])
316
+ if (rcvLen <= 0)
317
+ break
318
+ puts("受信データを取得できないため、接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
319
+ @ReceiveStatus = DISCONNECT_REASON_SERVER_IREGULAR
320
+ raise("受信データを取得できないため、接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
321
+ #elsif (@ctsClient.IsCancellationRequested)
322
+ # @ReceiveStatus = @DISCONNECT_REASON_CANCEL
323
+ # raise("キャンセルリクエストが発生しました。接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
324
+ end
325
+
326
+ else
327
+ @ReceiveStatus = DISCONNECT_REASON_CLIENT_IREGULAR
328
+ raise("受信データを取得できないため、接続先から切断します。\r\n受信データサイズ[#{rcvLen}]")
329
+ end
330
+
331
+ rescue Exception => ex
332
+ #タイムアウト時はWait
333
+ if(!ex.to_s.include?("end of file"))
334
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
335
+ puts("【CL】接続先からのデータ受信エラー:%s}" % [ex])
336
+ raise(ex)
337
+ end
338
+ #next
339
+ end
340
+
341
+ #受信データ解析
342
+ if (rcvLen > 0)
343
+ case rcvBuf[0]
344
+ when MSG_ACK_START_COMM
345
+ if (rcvLen != ackStartComm.total_len)
346
+ #受信データサイズが不正
347
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
348
+ raise("不正なデータを受信したため、接続先から切断します。\r\nnメッセージID[0x%02x], 受信サイズ[%d]" % [ackStartComm.id, rcvLen])
349
+ end
350
+ ackStartComm.ack_code = rcvBuf[ackStartComm.INDEX_ACK_CODE]
351
+ ackStartComm.err_code = rcvBuf[ackStartComm.INDEX_ERR_CODE]
352
+ HzTrace.traceCommMessage("【CL】通信開始応答受信(0x%02x):Ack Code[0x%02x], Error Code[0x%02x]" % [ackStartComm.id, ackStartComm.ack_code, ackStartComm.err_code])
353
+ if (ackStartComm.ack_code == ackStartComm.ACK_CODE_NG)
354
+ #エラー発生時
355
+ @ReceiveStatus = ackStartComm.err_code
356
+ evNotifyMessageEvent("接続先からエラーコードを受信しました。\r\nメッセージID[0x%02x], エラーコード[0x%02x]" % [ackStartComm.id, ackStartComm.err_code], ackStartComm.id, ackStartComm.err_code)
357
+ rcvEndFlg = true
358
+ end
359
+ @ackStartCommAutoResetEvent.push(@QUEUE_RECEIVED)
360
+ when MSG_ACK_SEND_SPEECH_DATA
361
+ if (rcvLen != ackSendSpeechData.total_len)
362
+ #受信データサイズが不正
363
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
364
+ raise("不正なデータを受信したため、接続先から切断します。\r\nメッセージID[0x%02x], 受信サイズ[%d]" % [ackSendSpeechData.id, rcvLen])
365
+ end
366
+ ackSendSpeechData.ack_code = rcvBuf[ackSendSpeechData.INDEX_ACK_CODE]
367
+ ackSendSpeechData.err_code = rcvBuf[ackSendSpeechData.INDEX_ERR_CODE]
368
+ HzTrace.traceCommMessage("【CL】読み上げデータ送信応答受信(0x%02x):Ack Code[0x%02x], Error Code[0x%02x]" % [ackSendSpeechData.id, ackSendSpeechData.ack_code, ackSendSpeechData.err_code])
369
+ if (ackSendSpeechData.ack_code == ackSendSpeechData.ACK_CODE_NG)
370
+ #エラー発生時
371
+ @ReceiveStatus = ackSendSpeechData.err_code
372
+ evNotifyMessageEvent("接続先からエラーコードを受信しました。\r\nメッセージID[0x%02x], エラーコード[0x%02x]" % [ackSendSpeechData.id, ackSendSpeechData.err_code], ackSendSpeechData.id, ackSendSpeechData.err_code)
373
+ rcvEndFlg = true
374
+ end
375
+ @ackSendSpeechDataAutoResetEvent.push(@QUEUE_RECEIVED)
376
+ when MSG_NOTIFY_COMPLETE_SPEECH
377
+ if (rcvLen != notifyCompleteReading.total_len)
378
+ #受信データサイズが不正
379
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
380
+ raise("不正なデータを受信したため、接続先から切断します。\r\nnメッセージID[0x%02x], 受信サイズ[%d]" % [notifyCompleteReading.id, rcvLen])
381
+ end
382
+ notifyCompleteReading.result = rcvBuf[notifyCompleteReading.INDEX_RESULT]
383
+ notifyCompleteReading.time_stamp = rcvBuf[notifyCompleteReading.INDEX_TIME_STAMP..(notifyCompleteReading.INDEX_TIME_STAMP + 7)]
384
+ HzTrace.traceCommMessage("【CL】読み上げ完了通知受信(0x%02x):Result[0x%02x], TimeStamp[%s]" % [notifyCompleteReading.id, notifyCompleteReading.result, notifyCompleteReading.time_stamp.pack("C*")])
385
+ #コールバック関数呼び出し
386
+ evNotifyCompeteReading(notifyCompleteReading.result, notifyCompleteReading.time_stamp.pack("C*"))
387
+ when MSG_NOTIFY_STOP_COMM
388
+ if (rcvLen != notifyStopComm.total_len)
389
+ #受信データサイズが不正
390
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
391
+ raise("不正なデータを受信したため、接続先から切断します。\r\nメッセージID[{0:x2}], 受信サイズ[{1}]", notifyStopComm.id, rcvLen)
392
+ end
393
+ notifyStopComm.stop_code = rcvBuf[notifyStopComm.INDEX_STOP_CODE]
394
+ @ReceiveStatus = notifyStopComm.reason_code
395
+ HzTrace.traceCommMessage("【CL】通信停止通知受信(0x%02x):Stop Code[0x%02x], Reason Code[0x%02x]" % [notifyStopComm.id, notifyStopComm.stop_code, notifyStopComm.reason_code])
396
+ evNotifyReceivedDisConnectEvent(("クライアント: " + "接続先から通信停止通知を受信しました。接続先から切断します。\r\nメッセージID[0x%02x], 停止コード[0x%02x], 理由コード[0x%02x]" % [notifyStopComm.id, notifyStopComm.stop_code, notifyStopComm.reason_code]), @ReceiveStatus)
397
+ rcvEndFlg = true
398
+ else
399
+ @ReceiveStatus = @DISCONNECT_REASON_SERVER_IREGULAR
400
+ raise("不正なデータを受信しました。Message ID[0x%02x], 受信サイズ[%d]", rcvBuf[0], rcvLen)
401
+
402
+ end #case
403
+ if (rcvEndFlg)
404
+ break
405
+ end
406
+ end #if(rcvLen > 0)
407
+
408
+
409
+ end #loop do
410
+
411
+ rescue Exception => ex
412
+ evNotifyReceivedDisConnectEvent("受信スレッド: %s" % [ex], @ReceiveStatus)
413
+ #if (ex.HResult != HaruZiraMessage.HRSEULT_SOCKET_CLOSED)
414
+ # #notifyEndCommProc()
415
+ # evNotifyReceivedDisConnectEvent("受信スレッド: " + ex.Message, @ReceiveStatus)
416
+ #end
417
+ ensure
418
+ if (@cltSocket != nil)
419
+ @cltSocket.close()
420
+ @cltSocket = nil
421
+ end
422
+ #同期オブジェクトの解除
423
+ @ackStartCommAutoResetEvent.push(@QUEUE_RECEIVED)
424
+ @ackSendSpeechDataAutoResetEvent.push(@QUEUE_RECEIVED)
425
+ HzTrace.traceCommMessage("受信ワーカースレッド終了")
426
+ end
427
+ end #Thread
428
+ end #def
429
+
430
+ # <summary>
431
+ # 通信開始要求(0x00)
432
+ # </summary>
433
+ # <param name="name">アカウント名</param>
434
+ # <param name="passwd">パスワード</param>
435
+ # <param name="strEnc">暗号化キー</param>
436
+ # <returns>true:OK, false:NG</returns>
437
+ def reqStartCommProc(name = "", passwd = "", strEncKey = "")
438
+ data = nil
439
+ len = 0
440
+ @ReceiveStatus = 0
441
+ reqStartComm = MsgReqStartComm.new()
442
+ ret = false
443
+
444
+ begin
445
+ #接続状態の確認
446
+ if (@cltSocket != nil)
447
+ #if (@work_rcv.alive)
448
+ @cltSocket.close()
449
+ @cltSocket = nil
450
+ #end
451
+ begin
452
+ Timeout.timeout(THREAD_JOIN_TIME_OUT) do
453
+ @work_rcv.join
454
+ end
455
+ rescue Timeout::Error => ex
456
+ #スレッド終了待ちのタイムアウトが発生しました。スレッドを強制終了しました。
457
+ Thread.kill(@work_rcv)
458
+ ensure
459
+ end
460
+ end
461
+
462
+ #接続
463
+ @cltSocket = TCPSocket.open(@ServerIP, @ServerPortNo)
464
+ #puts "接続OK"
465
+
466
+ @ackStartCommAutoResetEvent = Queue.new
467
+ @ackSendSpeechDataAutoResetEvent = Queue.new
468
+
469
+ #受信ワーカータスク起動
470
+ receiveWorker
471
+ sleep 0.5
472
+
473
+ #通信開始要求(0x00)
474
+ if(name.strip != "" && passwd.strip != "")
475
+ reqStartComm.cer_flg = reqStartComm.CER_FLG_ON
476
+ else
477
+ reqStartComm.cer_flg = reqStartComm.CER_FLG_OFF
478
+ end
479
+
480
+ if (strEncKey.strip != "" && reqStartComm.cer_flg == reqStartComm.CER_FLG_ON)
481
+ #暗号化
482
+ reqStartComm.enc_flg = reqStartComm.ENC_FLG_ON
483
+ reqStartComm.passwd = @encryption.cipherEncryption(passwd, EncryptionType::AesCbcPkcs7, strEncKey)
484
+ #p reqStartComm.passwd
485
+ #Debug
486
+ decPasswd = @encryption.cipherDecryption(EncryptionType::AesCbcPkcs7, reqStartComm.passwd.pack("C*"), strEncKey)
487
+ HzTrace.traceCommMessage("複合後パスワード:#{decPasswd}")
488
+ else
489
+ reqStartComm.enc_flg = reqStartComm.ENC_FLG_OFF
490
+ reqStartComm.passwd = passwd.encode("UTF-8").unpack("C*")
491
+ end
492
+
493
+ reqStartComm.port = @ReceivePort
494
+ if(name != "" && passwd != "")
495
+ reqStartComm.name = name.encode("UTF-8").unpack("C*")
496
+ reqStartComm.name_len = reqStartComm.name.length
497
+ reqStartComm.passwd_len = reqStartComm.passwd.length
498
+ #puts "account[#{reqStartComm.name.pack("C*")}] len:#{reqStartComm.name_len}, passwd len: #{reqStartComm.passwd_len}"
499
+ end
500
+ len, data = reqStartComm.makeSendData()
501
+ #p len, data
502
+ if(len > 0)
503
+ @cltSocket.write(data.pack("C*"))
504
+ @cltSocket.flush
505
+ else
506
+ raise("送信データの生成エラー。\r\n通信処理を停止します。")
507
+ end
508
+ @ackStartCommAutoResetEvent.clear
509
+
510
+ HzTrace.traceCommMessage("【CL】通信開始要求送信(0x%02x):Cer[%d] Enc[%d], Port[%d], Name[%s], Passwd[%s], Name Len[%d], Passwd Len[%d]" % \
511
+ [reqStartComm.id, reqStartComm.cer_flg, reqStartComm.enc_flg, reqStartComm.port, reqStartComm.name != nil ? name : "", \
512
+ reqStartComm.passwd != nil ? passwd : "", reqStartComm.name_len, reqStartComm.passwd_len])
513
+
514
+ #通信開始応答受信(0x10)
515
+ begin
516
+ Timeout.timeout(@ReceiveAckTimeOut) do
517
+ qret = @ackStartCommAutoResetEvent.pop
518
+ end
519
+ rescue Timeout::Error => ex
520
+ #応答待ちのタイムアウトが発生しました。通信処理を中断しました。
521
+ puts("【CL】通信開始応答受信(0x%02x):待機結果[%s]" % [reqStartComm.id, "Time Out"])
522
+ evNotifyMessageEvent("応答待ちのタイムアウトが発生しました。通信処理を中断します。", reqStartComm.id, HZ_ERROR_RECEIVE_TIMEOUT)
523
+ return false
524
+ else
525
+ if(@ReceiveStatus != 0x00)
526
+ raise("通信中にエラーが発生しました。\r\n通信処理を中断します。")
527
+ else
528
+ HzTrace.traceCommMessage("【CL】通信開始応答受信(0x%02x):待機結果[%s]" % [reqStartComm.id, "OK"])
529
+ end
530
+ ensure
531
+ @ackStartCommAutoResetEvent.clear
532
+ end
533
+
534
+ ret = true
535
+ rescue => ex
536
+ evNotifyMessageEvent(ex, reqStartComm.id, HZ_ERROR_OTHER_REASON)
537
+ puts("クライアント: %s" % [ex])
538
+ if (@cltSocket != nil)
539
+ #if (@work_rcv.alive)
540
+ @cltSocket.close()
541
+ @cltSocket = nil
542
+ #end
543
+ end
544
+ ret = false
545
+ ensure
546
+ return ret
547
+ end
548
+ end
549
+
550
+ # <summary>
551
+ # 通信終了通知(0x01)
552
+ # </summary>
553
+ # <param name="err_code">パスワード</param>
554
+ # <returns>true:OK, false:NG</returns>
555
+ def notifyEndCommProc(err_code)
556
+ notifyEndComm = MsgNotifyEndComm.new()
557
+ data = nil
558
+ len = 0
559
+ @ReceiveStatus = 0
560
+ ret = false
561
+
562
+ begin
563
+ #接続状態の確認
564
+ if (@cltSocket == nil)
565
+ return true
566
+ end
567
+
568
+ #通信終了通知(0x01)
569
+ if(err_code == notifyEndComm.ERR_CODE_NONE)
570
+ #正常
571
+ notifyEndComm.end_code = notifyEndComm.END_CODE_OK
572
+ notifyEndComm.err_code = notifyEndComm.ERR_CODE_NONE
573
+ else
574
+ #エラー有
575
+ notifyEndComm.end_code = notifyEndComm.END_CODE_NG
576
+ notifyEndComm.err_code = err_code
577
+ end
578
+
579
+ len, data = notifyEndComm.makeSendData()
580
+ #p len, data
581
+ if(len > 0)
582
+ @cltSocket.write(data.pack("C*"))
583
+ @cltSocket.flush
584
+ else
585
+ raise("送信データの生成エラー。\r\n通信処理を停止します。")
586
+ end
587
+
588
+ HzTrace.traceCommMessage("【CL】通信終了通知送信(0x%02x):End Code[0x%02x], Error Code[0x%02x]" % [notifyEndComm.id, notifyEndComm.end_code, notifyEndComm.err_code])
589
+
590
+ #サーバーが受信することを考慮
591
+ sleep(3)
592
+
593
+ begin
594
+ Timeout.timeout(THREAD_JOIN_TIME_OUT) do
595
+ @work_rcv.join
596
+ end
597
+ rescue Timeout::Error => ex
598
+ #スレッド終了待ちのタイムアウトが発生しました。スレッドを強制終了しました。
599
+ Thread.kill(@work_rcv)
600
+ ensure
601
+ if (@cltSocket != nil)
602
+ @cltSocket.close()
603
+ end
604
+ end
605
+
606
+ ret = true
607
+ rescue => ex
608
+ evNotifyMessageEvent(ex, notifyEndComm.id, HZ_ERROR_OTHER_REASON)
609
+
610
+ #if (ex.HResult != HaruZiraMessage.HRSEULT_SOCKET_CLOSED)
611
+ # evNotifyMessageEvent("クライアント: " + ex.Message)
612
+ #end
613
+
614
+ ret = false
615
+ ensure
616
+ return ret
617
+ end
618
+ end
619
+
620
+ # <summary>
621
+ # 読み上げデータ送信(手動)
622
+ # </summary>
623
+ # <returns>OK:タイムスタンプ文字列(00:00:00形式), NG:nil</returns>
624
+ def sendSpeechData()
625
+ data = nil
626
+ len = 0
627
+ @ReceiveStatus = 0
628
+ sendSpeechData = MsgSendSpeechData.new()
629
+ ackSendSpeechData = MsgAckSendSpeechData.new()
630
+ t = Time.now
631
+ timeStamp = "%02d:%02d:%02d" % [t.hour, t.min, t.sec]
632
+
633
+ begin
634
+ if (@cltSocket == nil)
635
+ raise("未接続です。\r\n送信先へ接続して下さい。")
636
+ end
637
+
638
+
639
+ #読み上げデータ送信(0x03)
640
+ if (@ReqSendDataAccountName != "" && @ReqSendDataEncryptKey != "")
641
+ #暗号化
642
+ sendSpeechData.enc_flg = sendSpeechData.ENC_FLG_ON
643
+ sendSpeechData.data = @encryption.cipherEncryption(@ReqSendDataText.encode("UTF-8"), EncryptionType::AesCbcPkcs7, @ReqSendDataEncryptKey)
644
+ else
645
+ #平文
646
+ sendSpeechData.enc_flg = sendSpeechData.ENC_FLG_OFF
647
+ sendSpeechData.data = @ReqSendDataText.encode("UTF-8").unpack("C*")
648
+ end
649
+ #p sendSpeechData.data
650
+
651
+ if(@ReqSendDataAccountName != "")
652
+ sendSpeechData.name = @ReqSendDataAccountName.encode("UTF-8").unpack("C*")
653
+ sendSpeechData.name_len = sendSpeechData.name.length
654
+ end
655
+ sendSpeechData.data_type = @ReqSendDataSpeechMode
656
+ sendSpeechData.priority = @ReqSendDataSpeechLevel
657
+ sendSpeechData.lang_code = @ReqSendDataSpeechLocaleId
658
+ sendSpeechData.gender = @ReqSendDataSpeechGender
659
+ sendSpeechData.age = @ReqSendDataSpeechAge
660
+ sendSpeechData.repeat = @ReqSendDataSpeechRepeat
661
+ sendSpeechData.time_stamp = timeStamp.unpack("C*")
662
+ sendSpeechData.size = sendSpeechData.data.length
663
+ @SendDataLength = sendSpeechData.size #Debug用
664
+
665
+ len, data = sendSpeechData.makeSendData()
666
+ #p len, data
667
+ #p len
668
+ if(len > 0)
669
+ @cltSocket.write(data.pack("C*"))
670
+ @cltSocket.flush
671
+ else
672
+ raise("送信データの生成エラー。\r\n通信処理を停止します。")
673
+ end
674
+ @ackSendSpeechDataAutoResetEvent.clear
675
+
676
+ HzTrace.traceCommMessage("【CL】読み上げデータ送信(0x%02x):Enc[%d], Size[%d]" % [sendSpeechData.id, sendSpeechData.enc_flg, sendSpeechData.size])
677
+
678
+
679
+ #読み上げデータ送信応答待機(0x12)
680
+ begin
681
+ Timeout.timeout(@ReceiveAckTimeOut) do
682
+ qret = @ackSendSpeechDataAutoResetEvent.pop
683
+ end
684
+ rescue Timeout::Error => ex
685
+ #応答待ちのタイムアウトが発生しました。通信処理を中断しました。
686
+ timeStamp = nil
687
+ puts("【CL】読み上げデータ送信応答受信(0x%02x):待機結果[%s]" % [sendSpeechData.id, "Time Out"])
688
+ evNotifyMessageEvent("応答待ちのタイムアウトが発生しました。通信処理を中断します。", sendSpeechData.id, HZ_ERROR_RECEIVE_TIMEOUT)
689
+ else
690
+ if(@ReceiveStatus != 0x00)
691
+ timeStamp = nil
692
+ return nil
693
+ end
694
+ HzTrace.traceCommMessage("【CL】読み上げデータ送信応答受信(0x%02x):待機結果[%s]" % [sendSpeechData.id, "OK"])
695
+ ensure
696
+ @ackSendSpeechDataAutoResetEvent.clear
697
+ end
698
+
699
+ rescue => ex
700
+ evNotifyMessageEvent(ex, sendSpeechData.id, HZ_ERROR_OTHER_REASON)
701
+ timeStamp = nil
702
+ ensure
703
+ return timeStamp
704
+ end
705
+ end
706
+
707
+ # <summary>
708
+ # 読み上げデータ送信(自動)
709
+ # </summary>
710
+ # <returns>OK:タイムスタンプ文字列(00:00:00形式), NG:nil</returns>
711
+ def sendSpeechDataEx()
712
+ timeStamp = ""
713
+ notifyEndComm = MsgNotifyEndComm.new()
714
+
715
+ begin
716
+
717
+ #電文シーケンス開始
718
+ #通信開始要求(0x00)
719
+ if (@ReqSendDataAccountName != nil && @ReqSendDataPasswd != nil && @ReqSendDataEncryptKey != nil)
720
+ #暗号化パスワード認証
721
+ retStatus = reqStartCommProc(@ReqSendDataAccountName, @ReqSendDataPasswd, @ReqSendDataEncryptKey)
722
+ elsif (@ReqSendDataAccountName != nil && @ReqSendDataPasswd != nil)
723
+ #パスワード認証
724
+ retStatus = reqStartCommProc(@ReqSendDataAccountName, @ReqSendDataPasswd)
725
+ else
726
+ #認証無
727
+ retStatus = reqStartCommProc()
728
+ end
729
+ if (!retStatus)
730
+ puts("【CL】通信開始応答受信(0x%02x):待機結果[%s]" % [reqStartComm.id, "Time Out"])
731
+ raise("通信開始要求メッセージ送信に失敗しました。\r\n通信処理を中断します。")
732
+ end
733
+
734
+ #非同期メッセージ受信タスク起動
735
+ if(@listenTask == nil)
736
+ @listenTask = Thread.start do
737
+ listenerTask()
738
+ end
739
+ end
740
+
741
+ #読み上げデータ送信(0x03)
742
+ if (@ReqSendDataAccountName != nil && @ReqSendDataEncryptKey != nil)
743
+ #暗号化(アカウント名および暗号化キー有)
744
+ @ReqSendDataEncrypt = true
745
+ elsif (@ReqSendDataAccountName == nil && @ReqSendDataEncryptKey != nil)
746
+ #暗号化(暗号化キーのみ)エラーケース
747
+ @ReqSendDataAccountName = ""
748
+ @ReqSendDataEncrypt = true
749
+ elsif (@ReqSendDataAccountName != nil && @ReqSendDataEncryptKey == nil)
750
+ #平文(アカウント名のみ)
751
+ @ReqSendDataEncrypt = false
752
+ @ReqSendDataEncryptKey = ""
753
+ else
754
+ #平文(認証が有効の場合はエラーとなる)
755
+ @ReqSendDataAccountName = ""
756
+ @ReqSendDataEncrypt = false
757
+ @ReqSendDataEncryptKey = ""
758
+ end
759
+ timeStamp = sendSpeechData()
760
+
761
+
762
+ #通信終了通知(0x01)
763
+ if(timeStamp == nil || @ReceiveStatus != 0x00)
764
+ notifyEndCommProc(notifyEndComm.ERR_CODE_OTHER_REASONS)
765
+ else
766
+ notifyEndCommProc(notifyEndComm.ERR_CODE_NONE)
767
+ end
768
+
769
+ rescue => ex
770
+ HzTrace.traceCommMessage("%s" % [ex])
771
+ timeStamp = nil
772
+ ensure
773
+ return timeStamp
774
+ end
775
+ end
776
+
777
+ # <summary>
778
+ # 非同期メッセージ受信スレッドの終了
779
+ # </summary>
780
+ def cancelAsynchronousListener()
781
+ if (@listenTask != nil)
782
+ @listenTask.kill
783
+ @listenTask = nil
784
+ HzTrace.traceCommMessage("非同期メッセージ受信スレッドをキャンセルしました。")
785
+ end
786
+ end
787
+
788
+ # <summary>
789
+ # 読み上げデータ送信の停止(中断)
790
+ # </summary>
791
+ def stopSendSpeechData()
792
+ if (@tcpSvr != nil)
793
+ @tcpSvr.kill
794
+ @tcpSvr = nil
795
+ HzTrace.traceCommMessage("読み上げデータ送信処理をキャンセルしました。")
796
+ end
797
+ end
798
+
799
+ end