CS+ と IronPython を利用した自動化の取り組み
修訂 | 8b7346f2d7aaa9a23aa6f01f2e47b0bfb2171f0a (tree) |
---|---|
時間 | 2015-11-11 23:45:32 |
作者 | Yasushi Tanaka <tanaka_yasushi2008@yaho...> |
Commiter | Yasushi Tanaka |
initial release
@@ -0,0 +1,548 @@ | ||
1 | +#coding:utf-8 | |
2 | + | |
3 | +# | |
4 | +# CLRインポート | |
5 | +# | |
6 | +import clr | |
7 | +clr.AddReferenceByPartialName("System.Windows.Forms") | |
8 | +from System.Windows.Forms import * | |
9 | +clr.AddReferenceByPartialName("System.Drawing") | |
10 | +from System.Drawing import * | |
11 | + | |
12 | +# | |
13 | +# ライブラリインポート | |
14 | +# | |
15 | +import os | |
16 | +import datetime | |
17 | +import time | |
18 | + | |
19 | +# | |
20 | +# スクリプト開始 | |
21 | +# | |
22 | +common.OutputPanel("Pythonスクリプトを開始しました", MessageType.Information) | |
23 | +print "Pythonスクリプトを開始しました" | |
24 | + | |
25 | +# | |
26 | +# プロジェクトオープンされているか確認 | |
27 | +# | |
28 | +common.OutputPanel("プロジェクト確認中です", MessageType.Information) | |
29 | +print "プロジェクト確認中です" | |
30 | +if project.IsOpen != True: | |
31 | + common.OutputPanel("プロジェクトがオープンされていません", MessageType.Error) | |
32 | + print "プロジェクトがオープンされていません" | |
33 | + sys.exit() | |
34 | +common.OutputPanel("プロジェクト確認しました", MessageType.Information) | |
35 | +print "プロジェクト確認しました" | |
36 | + | |
37 | +# | |
38 | +# アクティブプロジェクト名からPythonベースパスを作成 | |
39 | +# (プロジェクト名に日本語文字を含めないこと) | |
40 | +# basePath:プロジェクトパス/Python/ | |
41 | +# | |
42 | +common.OutputPanel("Python作業パスを確認中です", MessageType.Information) | |
43 | +print "Python作業パスを確認中です" | |
44 | +basePath = project.Path.rpartition('\\')[0] + project.Path.rpartition('\\')[1] | |
45 | +basePath = basePath + "Python" | |
46 | +# パスが存在しなければ作成(作成できたかどうかのチェックは行わない) | |
47 | +if os.path.exists(basePath) != True: | |
48 | + os.mkdir(basePath) | |
49 | +# パスの存在をチェック | |
50 | +if os.path.exists(basePath) != True: | |
51 | + common.OutputPanel("フォルダ作成に失敗しました", MessageType.Error) | |
52 | + print "フォルダ作成に失敗しました" | |
53 | + sys.exit() | |
54 | +# パスがディレクトリか、またはファイルかチェック | |
55 | +if os.path.isdir(basePath) != True: | |
56 | + common.OutputPanel("Pythonフォルダがファイルとして存在しています", MessageType.Error) | |
57 | + print "Pythonフォルダがファイルとして存在しています" | |
58 | + sys.exit() | |
59 | +# 末尾にパス区切り文字を追加 | |
60 | +basePath = basePath + "\\" | |
61 | +common.OutputPanel("Pythonパスを確認しました " + basePath, MessageType.Information) | |
62 | +print "Python作業パスを確認しました " + basePath | |
63 | + | |
64 | +# | |
65 | +# ログファイルを作成 | |
66 | +# scriptName:スクリプトファイル名(.pyは含まない) | |
67 | +# logPath:プロジェクトパス/Python/スクリプトファイル名_日付_時刻.log | |
68 | +# | |
69 | +logDate = datetime.datetime.now() | |
70 | +scriptName = os.path.basename(__file__).rpartition(".")[0] | |
71 | +logPath = basePath + scriptName + logDate.strftime("_%Y%m%d_%H%M%S.log") | |
72 | +logFile = open(logPath, "a") | |
73 | +# オープンできたかチェック | |
74 | +if logFile.closed == True: | |
75 | + common.OutputPanel("ログファイルを追加オープンできません", MessageType.Error) | |
76 | + print "ログファイルを追加オープンできません" | |
77 | + sys.exit() | |
78 | + | |
79 | +# | |
80 | +# ログ番号を初期化 | |
81 | +# | |
82 | +logNum = 0 | |
83 | + | |
84 | +#-[ 汎用関数 ]---------------------------------------------------------------- | |
85 | + | |
86 | +# | |
87 | +# 関数:ログ出力 | |
88 | +# | |
89 | +def output_log(msg, err=False): | |
90 | + # ログ番号をフォーマット | |
91 | + global logNum | |
92 | + numMsg = "[%06d] " % logNum | |
93 | + | |
94 | + # ログ番号を+1 | |
95 | + logNum = logNum + 1 | |
96 | + | |
97 | + # 日付をフォーマット | |
98 | + dtNow = datetime.datetime.now() | |
99 | + dtMsg = dtNow.strftime("%Y-%m-%d %H:%M:%S ") | |
100 | + | |
101 | + # [ログ番号] 日付 時間 文字列 | |
102 | + numMsg = numMsg + dtMsg + msg | |
103 | + | |
104 | + # パネル | |
105 | + if err == True: | |
106 | + common.OutputPanel(numMsg, MessageType.Error) | |
107 | + else: | |
108 | + common.OutputPanel(numMsg, MessageType.Information) | |
109 | + | |
110 | + # Pythonコンソール | |
111 | + print numMsg | |
112 | + | |
113 | + # ログ | |
114 | + numMsg = numMsg + "\n" | |
115 | + logFile.write(numMsg.encode('cp932')) | |
116 | + | |
117 | + # エラーなら、ここでスクリプト打ち切り | |
118 | + if err == True: | |
119 | + # 中断 | |
120 | + logFile.close() | |
121 | + sys.exit() | |
122 | + | |
123 | + # コンソールをフラッシュ | |
124 | + sys.stdout.flush() | |
125 | + | |
126 | +# | |
127 | +# 関数:スクリーンキャプチャの取得とセーブ(マルチディスプレイ対応) | |
128 | +# | |
129 | +def save_screen(name): | |
130 | + # スクリーン番号を表すインデックスを初期化 | |
131 | + index = 0 | |
132 | + | |
133 | + # スクリーン毎にループ | |
134 | + for scr in Screen.AllScreens: | |
135 | + # 現在日付+スクリーン番号+パラメータからパス名を作成 | |
136 | + dtNow = datetime.datetime.now() | |
137 | + dtMsg = dtNow.strftime("%Y%m%d_%H%M%S") | |
138 | + scrMsg = "_%1d_" % index | |
139 | + path = basePath + dtMsg + scrMsg + name + ".png" | |
140 | + | |
141 | + # ログ出力 | |
142 | + output_log("スクリーンキャプチャを保存しました " + path) | |
143 | + | |
144 | + # スクリーン毎のサイズを表すRectangle型を取得 | |
145 | + rect = scr.Bounds | |
146 | + | |
147 | + # ビットマップとグラフィックを併用してスクリーンキャプチャ | |
148 | + bmp = Bitmap(rect.Width, rect.Height) | |
149 | + grp = Graphics.FromImage(bmp) | |
150 | + grp.CopyFromScreen(Point(0, 0), Point(0, 0), Size(rect.Width, rect.Height)) | |
151 | + | |
152 | + # PNG形式でファイルに保存 | |
153 | + bmp.Save(path, Imaging.ImageFormat.Png) | |
154 | + | |
155 | + # 後片付け | |
156 | + grp.Dispose() | |
157 | + bmp.Dispose() | |
158 | + | |
159 | + # 次のスクリーンへ | |
160 | + index = index + 1 | |
161 | + | |
162 | +# | |
163 | +# 関数:指定msだけ時間待ち | |
164 | +# | |
165 | +def sleep_ms(ms=1000): | |
166 | + # ログ | |
167 | + msMsg = "時間待ち %d(ms)" % ms | |
168 | + output_log(msMsg) | |
169 | + | |
170 | + # スリープ | |
171 | + time.sleep(ms * 0.001) | |
172 | + | |
173 | +#-[ ビルド ]------------------------------------------------------------------ | |
174 | + | |
175 | +# | |
176 | +# 関数:ビルド | |
177 | +# | |
178 | +def build_project(all): | |
179 | + # ログ表示 | |
180 | + if all == True: | |
181 | + output_log("リビルドしています") | |
182 | + else: | |
183 | + output_log("通常ビルドしています") | |
184 | + | |
185 | + # パラメータに応じて通常ビルドまたはリビルド | |
186 | + ret = build.All(all, True) | |
187 | + | |
188 | + # 結果確認 | |
189 | + if ret == True: | |
190 | + output_log("ビルド成功しました") | |
191 | + else: | |
192 | + output_log("ビルド失敗しました", True) | |
193 | + | |
194 | +# | |
195 | +# 関数:メッセージボックスでビルドタイプを選択 | |
196 | +# | |
197 | +def select_build(): | |
198 | + # メッセージボックスでビルドタイプを選択 | |
199 | + output_log("ビルドタイプ選択(はい:通常ビルド いいえ:リビルド)") | |
200 | + ret = MessageBox.Show("通常ビルドしますか?", "ビルド選択", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) | |
201 | + | |
202 | + # キャンセルされたら終了する | |
203 | + if ret == DialogResult.Cancel: | |
204 | + output_log("キャンセルされました", True) | |
205 | + | |
206 | + # 結果を判定 | |
207 | + if ret == DialogResult.Yes: | |
208 | + rebuild = False | |
209 | + else: | |
210 | + rebuild = True | |
211 | + return rebuild | |
212 | + | |
213 | +#-[ デバッガ ]---------------------------------------------------------------- | |
214 | + | |
215 | +# | |
216 | +# 関数:デバッガをE1(Serial)へ変更 | |
217 | +# | |
218 | +def change_debugger_e1s(): | |
219 | + # ログ表示 | |
220 | + output_log("デバッガをE1(Serial)へ変更しています") | |
221 | + | |
222 | + # デバッガ変更 | |
223 | + if e1 == True: | |
224 | + ret = debugger.DebugTool.Change(DebugTool.E1Serial) | |
225 | + else: | |
226 | + ret = debugger.DebugTool.Change(DebugTool.Simulator) | |
227 | + | |
228 | + # 結果評価 | |
229 | + if ret == True: | |
230 | + output_log("デバッガをE1(Serial)へ変更しました") | |
231 | + else: | |
232 | + output_log("デバッガのE1(Serial)への変更に失敗しました", True) | |
233 | + | |
234 | +# | |
235 | +# 関数:デバッガをE1(LPD)へ変更 | |
236 | +# | |
237 | +def change_debugger_e1l(): | |
238 | + # ログ表示 | |
239 | + output_log("デバッガをE1(LPD)へ変更しています") | |
240 | + | |
241 | + # デバッガ変更 | |
242 | + ret = debugger.DebugTool.Change(DebugTool.E1Lpd) | |
243 | + | |
244 | + # 結果評価 | |
245 | + if ret == True: | |
246 | + output_log("デバッガをE1(LPD)へ変更しました") | |
247 | + else: | |
248 | + output_log("デバッガのE1(LPD)への変更に失敗しました", True) | |
249 | + | |
250 | +# | |
251 | +# 関数:デバッガをIECUBEへ変更 | |
252 | +# | |
253 | +def change_debugger_iecube(): | |
254 | + # ログ表示 | |
255 | + output_log("デバッガをIECUBEへ変更しています") | |
256 | + | |
257 | + # デバッガ変更 | |
258 | + ret = debugger.DebugTool.Change(DebugTool.Iecube) | |
259 | + | |
260 | + # 結果評価 | |
261 | + if ret == True: | |
262 | + output_log("デバッガをIECUBEへ変更しました") | |
263 | + else: | |
264 | + output_log("デバッガのIECUBEへの変更に失敗しました", True) | |
265 | + | |
266 | +# | |
267 | +# 関数:デバッガをSimへ変更 | |
268 | +# | |
269 | +def change_debugger_sim(): | |
270 | + # ログ表示 | |
271 | + output_log("デバッガをSimへ変更しています") | |
272 | + | |
273 | + # デバッガ変更 | |
274 | + ret = debugger.DebugTool.Change(DebugTool.Simulator) | |
275 | + | |
276 | + # 結果評価 | |
277 | + if ret == True: | |
278 | + output_log("デバッガをSimへ変更しました") | |
279 | + else: | |
280 | + output_log("デバッガのSimへの変更に失敗しました", True) | |
281 | + | |
282 | +# | |
283 | +# 関数:デバッガへ接続 | |
284 | +# | |
285 | +def connect_debugger(): | |
286 | + # ログ表示 | |
287 | + output_log("デバッガへ接続しています") | |
288 | + | |
289 | + # デバッガへ接続 | |
290 | + ret = debugger.Connect() | |
291 | + | |
292 | + # 結果評価 | |
293 | + if ret == True: | |
294 | + output_log("デバッガへ接続成功しました") | |
295 | + else: | |
296 | + output_log("デバッガへ接続できませんでした", True) | |
297 | + | |
298 | +# | |
299 | +# 関数:デバッガを切り離す | |
300 | +# | |
301 | +def disconnect_debugger(): | |
302 | + # ログ表示 | |
303 | + output_log("デバッガを切り離しています") | |
304 | + | |
305 | + # デバッガを切断 | |
306 | + ret = debugger.Disconnect() | |
307 | + | |
308 | + # 結果評価 | |
309 | + if ret == True: | |
310 | + output_log("デバッガを切断しました") | |
311 | + else: | |
312 | + output_log("デバッガを切断できませんでした", True) | |
313 | + | |
314 | +# | |
315 | +# 関数:デバッガが接続されていれば切り離す | |
316 | +# | |
317 | +def disconnect_if_connect(): | |
318 | + if debugger.IsConnected() == True: | |
319 | + if debugger.IsRunning == True: | |
320 | + debugger.Stop() | |
321 | + disconnect_debugger() | |
322 | + | |
323 | +# | |
324 | +# 関数:メッセージボックスでデバッガタイプを選択(E1Serial) | |
325 | +# | |
326 | +def select_debugger_e1s(): | |
327 | + # メッセージボックスでデバッガタイプを選択 | |
328 | + output_log("デバッガ選択(はい:E1(Serial) いいえ:Sim)") | |
329 | + ret = MessageBox.Show("E1(Serial)を使用しますか?", "デバッガ選択", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) | |
330 | + | |
331 | + # キャンセルされたら終了する | |
332 | + if ret == DialogResult.Cancel: | |
333 | + output_log("キャンセルされました", True) | |
334 | + | |
335 | + # 結果を判定 | |
336 | + if ret == DialogResult.Yes: | |
337 | + e1s = True | |
338 | + else: | |
339 | + e1s = False | |
340 | + return e1s | |
341 | + | |
342 | +#-[ 実行制御 ]---------------------------------------------------------------- | |
343 | + | |
344 | +# | |
345 | +# 関数:ロードモジュールをダウンロード | |
346 | +# | |
347 | +def download_module(): | |
348 | + # ログ表示 | |
349 | + output_log("ロードモジュールをダウンロードしています") | |
350 | + | |
351 | + # ダウンロード | |
352 | + ret = debugger.Download.LoadModule() | |
353 | + | |
354 | + # 結果評価 | |
355 | + if ret == True: | |
356 | + info = debugger.Download.Information() | |
357 | + output_log("ロードモジュールをダウンロードしました " + info[0].Name) | |
358 | + else: | |
359 | + output_log("ロードモジュールをダウンロードできませんでした", True) | |
360 | + | |
361 | +# | |
362 | +# 関数:プログラムをリセット後に実行 | |
363 | +# | |
364 | +def reset_and_go(): | |
365 | + # ログ表示 | |
366 | + output_log("リセット後スタートします") | |
367 | + | |
368 | + # リセット実行 | |
369 | + debugger.Run(RunOption.Normal) | |
370 | + | |
371 | +# | |
372 | +# 関数:プログラムを現在位置から実行 | |
373 | +# | |
374 | +def resume_and_go(): | |
375 | + # ログ表示 | |
376 | + output_log("現在位置から継続実行します") | |
377 | + | |
378 | + # 継続実行 | |
379 | + debugger.Go(GoOption.Normal) | |
380 | + | |
381 | +# | |
382 | +# 関数:強制ストップ | |
383 | +# | |
384 | +def force_stop(): | |
385 | + # ログ表示 | |
386 | + output_log("強制ストップします") | |
387 | + | |
388 | + # 強制ストップ | |
389 | + debugger.Stop() | |
390 | + | |
391 | +#-[ ブレークポイント ]-------------------------------------------------------- | |
392 | + | |
393 | +# | |
394 | +# 関数:ブレークポイントをすべて削除 | |
395 | +# | |
396 | +def clear_breakpoint(): | |
397 | + # ログ表示 | |
398 | + output_log("ブレークポイントをすべて削除します") | |
399 | + | |
400 | + # すべて削除 | |
401 | + ret = debugger.Breakpoint.Delete() | |
402 | + | |
403 | + # 結果評価 | |
404 | + if ret != True: | |
405 | + output_log("ブレークポイントを削除できませんでした", True) | |
406 | + | |
407 | +# | |
408 | +# 関数:実行時ブレークポイントを追加 | |
409 | +# | |
410 | +def add_execbreak(name, hardware=True): | |
411 | + # ブレークポイントオブジェクトを作成 | |
412 | + executeBreak = BreakCondition() | |
413 | + executeBreak.Address = name | |
414 | + if hardware == True: | |
415 | + executeBreak.BreakType = BreakType.Hardware | |
416 | + else: | |
417 | + executeBreak.BreakType = BreakType.Software | |
418 | + | |
419 | + # ブレークポイントを追加 | |
420 | + ret = debugger.Breakpoint.Set(executeBreak) | |
421 | + | |
422 | + # 結果評価 | |
423 | + if ret == True: | |
424 | + if hardware == True: | |
425 | + output_log("実行時ハードウェアブレークポイントを追加しました " + name) | |
426 | + else: | |
427 | + output_log("実行時ソフトウェアブレークポイントを追加しました " + name) | |
428 | + else: | |
429 | + output_log("ブレークポイントの追加に失敗しました " + name, True) | |
430 | + | |
431 | +# | |
432 | +# 関数:ブレークするまで待機 | |
433 | +# | |
434 | +def wait_until_break(): | |
435 | + # ログ表示 | |
436 | + output_log("ブレーク待ち") | |
437 | + | |
438 | + # ブレーク条件が無い限り、10ms待つ処理を続ける | |
439 | + while debugger.GetBreakStatus() == BreakStatus.None: | |
440 | + time.sleep(0.001) | |
441 | + sys.stdout.flush() | |
442 | + | |
443 | +# | |
444 | +# 関数:ブレーク時にPCからジャンプ | |
445 | +# | |
446 | +def view_break_pc(): | |
447 | + # PCを取得 | |
448 | + pc = debugger.GetPC() | |
449 | + | |
450 | + # ログ表示 | |
451 | + pcMsg = "%x" % pc | |
452 | + output_log("ブレークしました PC=0x" + pcMsg) | |
453 | + | |
454 | + # ジャンプ | |
455 | + debugger.Jump.Address(JumpType.Source, pc) | |
456 | + | |
457 | +#-[ ウォッチ ]---------------------------------------------------------------- | |
458 | + | |
459 | +# | |
460 | +# 関数:ウォッチで値を表示(DEC) | |
461 | +# | |
462 | +def watch_value_dec(name): | |
463 | + # ログ | |
464 | + output_log("ウォッチします " + name + " = (DEC):") | |
465 | + | |
466 | + # ウォッチで値を取得 | |
467 | + debugger.Watch.GetValue(name, WatchOption.Decimal) | |
468 | + | |
469 | +# | |
470 | +# 関数:ウォッチで値を表示(HEX) | |
471 | +# | |
472 | +def watch_value_hex(name): | |
473 | + # ログ | |
474 | + output_log("ウォッチします " + name + " = (HEX):") | |
475 | + | |
476 | + # ウォッチで値を取得 | |
477 | + debugger.Watch.GetValue(name, WatchOption.Hexdecimal) | |
478 | + | |
479 | +# | |
480 | +# 関数:ウォッチで値を設定 | |
481 | +# | |
482 | +def set_value(name, value, hex=True): | |
483 | + # ログ | |
484 | + output_log("変数を設定します " + name) | |
485 | + | |
486 | + # 値を設定 | |
487 | + debugger.Watch.SetValue(name, value) | |
488 | + | |
489 | + # 設定値を確認 | |
490 | + if hex == True: | |
491 | + debugger.Watch.GetValue(name, WatchOption.Hexdecimal) | |
492 | + else: | |
493 | + debugger.Watch.GetValue(name, WatchOption.Decimal) | |
494 | + | |
495 | +#-[ メイン ]-------------------------------------------------------- | |
496 | + | |
497 | +# | |
498 | +# メイン(ビルド) | |
499 | +# | |
500 | +rebuild = select_build() | |
501 | +build_project(rebuild) | |
502 | + | |
503 | +# | |
504 | +# メイン(デバッグ開始) | |
505 | +# | |
506 | +disconnect_if_connect() | |
507 | +e1s = select_debugger_e1s() | |
508 | +if e1s == True: | |
509 | + change_debugger_e1s() | |
510 | +else: | |
511 | + change_debugger_sim() | |
512 | +connect_debugger() | |
513 | +download_module() | |
514 | + | |
515 | +# | |
516 | +# メイン(ブレーク設定) | |
517 | +# | |
518 | +clear_breakpoint() | |
519 | +add_execbreak("R_TAU0_Channel0_Start") | |
520 | + | |
521 | +Condition = BreakCondition() | |
522 | +Condition.Address = "check_data" | |
523 | +debugger.Breakpoint.Set(Condition) | |
524 | +#add_execbreak("check_data") | |
525 | +reset_and_go() | |
526 | +wait_until_break() | |
527 | + | |
528 | + | |
529 | +view_break_pc() | |
530 | +watch_value_dec("g_int_data") | |
531 | +watch_value_hex("g_int_data") | |
532 | +sleep_ms() | |
533 | +save_screen("check_data") | |
534 | +set_value("g_int_data", 0xffff) | |
535 | +resume_and_go() | |
536 | +wait_until_break() | |
537 | +view_break_pc() | |
538 | +watch_value_hex("g_int_data") | |
539 | +sleep_ms() | |
540 | +save_screen("R_TAU0_Channel_Start") | |
541 | + | |
542 | + | |
543 | +# | |
544 | +# 終了 | |
545 | +# | |
546 | +disconnect_if_connect() | |
547 | +output_log("正常終了しました") | |
548 | +logFile.close() |