OSDN Git Service

git-svn-id: http://svn.osdn.jp/svnroot/mimic/trunk@96 47198e57-cb75-475f-84c4-a814cd6...
[mimic/MiMicSDK.git] / misc / MiMicVM / api.js / MiMicCore.js
1 /**\r
2  * @fileOverview 低レベルAPIを定義する。低レベルAPIは、MiMicRemoteMcuをインストールしたMCUとの通信クラスを提供する。\r
3  */\r
4 \r
5 /**\r
6  * MiMicが使用する関数、定数を定義する。\r
7  * @namespace\r
8  */\r
9 var MiMicLib=\r
10 {\r
11         /**\r
12          * aがundefinedであるかを真偽値で返す。\r
13          * @function\r
14          * @param {object} a\r
15          * 判定対象のオブジェクト\r
16          * @return {Boolean}\r
17          * aがundefinedであれば、trueである。\r
18          */     \r
19         isUndef:function isUndef(a){\r
20                 return typeof a==="undefined"\r
21         },\r
22         /**\r
23          * 連想配列をシャローコピーして複製する。\r
24          * @function\r
25          * @param {object} a\r
26          * 複製元のオブジェクトである。\r
27          * @return {object}\r
28          * 複製したオブジェクトである。\r
29          */     \r
30         cloneAssoc:function cloneAssoc(a)\r
31         {\r
32                 var r={};\r
33                 for(var i in a){\r
34                         r[i]=a[i];\r
35                 }\r
36                 return r;\r
37         }\r
38 }\r
39 \r
40 /**\r
41  * MiMicExceptionが使用するエラーコードと、その判定関数を定義する。\r
42  * エラーコードは、以下の形式の配列オブジェクトで表現する。\r
43  * <pre>\r
44  * [code:int,message:string]\r
45  * </pre>\r
46  * \r
47  * codeは31ビットのエラーコードである。ビットフィールドの意味は以下の通りである。\r
48  * <table>\r
49  * <tr><th>bit</th><th>name</th><th>discription</th></tr>\r
50  * <tr><td>30</td><td>ErrorBit</td><td>Error:1,OK:0</td></tr>\r
51  * <tr><td>29-24</td><td>Reserved</td><td>-</td></tr>\r
52  * <tr><td>23-16</td><td>ModuleID</td><td>0x00:unknown<br/>0x39:MiMic<br/>0xF0-0xFF: user define<br/>Other:Reserved<br/></td></tr>\r
53  * <tr><td>15-8</td><td>ClassID</td><td>0x00:unknown</td></tr>\r
54  * <tr><td>7-0</td><td>ErrorID</td><td></td></tr>\r
55  * </table>\r
56  * @namespace\r
57  * @example\r
58  * throw new MiMicException(MiMicError.NG);\r
59  */\r
60 var MiMicError=\r
61 {\r
62         /** 成功を示すエラー値\r
63          * @constant*/  \r
64         OK:[0x00000000,"OK"],\r
65         /** 失敗を示すエラー値。不明な場所で、不明な何かが、不明なエラーを起こしたことを示す。\r
66          * @constant*/  \r
67         NG:[0x40000000,"NG"],\r
68         /**\r
69          * エラーコードがOKか調べる。\r
70          * @function\r
71          * @param {Object as [MiMicErrorCode]} v\r
72          * 評価するオブジェクト\r
73          * @return {Boolean}\r
74          * エラーコードでなければ、trueを返す。\r
75          * @example\r
76          * MiMicError.isOK(MiMicError.OK);//true\r
77          */\r
78         isOK:function(v){\r
79                 return (0x40000000 & v)==0x00000000;\r
80         },\r
81         /*\r
82          * 定数定義
83          */\r
84         /** @private*/\r
85         MID_MiMic:0x00390000,\r
86         /** @private*/\r
87         CAID_RemoteMCU     :0x0100,     //\r
88         /** @private*/\r
89         CAID_LPCXPresso1769:0x0200      //リモートAPI\r
90         \r
91 }\r
92 \r
93 \r
94 /**\r
95  * 引数が1個のパターン。\r
96  * @name MiMicException.2\r
97  * @function\r
98  * @param {object} e\r
99  * eのクラスにより、動作が異なる。\r
100  * <ul>\r
101  * <li>{string} - MiMicException(MiMicError.NG,e)と等価である。</li>\r
102  * <li>{object as [MiMicErrorCode]} - エラーコードを指定して例外を生成する。エラーコードについては、MiMicErrorを参照</li>\r
103  * <li>{object} - MiMicException(MiMicError.NG,e.toString())と等価である。objectを文字列化して例外を生成する。</li>\r
104  * <li>{MiMicException} - codeとmessageを継承して例外を生成する。コールスタックを生成するときは、このパターンを使うこと。</li>\r
105  * </ul>\r
106  * @example\r
107  * throw new MiMicException(MiMicError.NG);\r
108  * throw new MiMicException("Error");\r
109  * try{\r
110  *       throw new MiMicException("Error");\r
111  * }catch(e){\r
112  *       throw new MiMicException(e);\r
113  * }\r
114  */\r
115 /**\r
116  * 引数が2個のパターン。追加メッセージを含めることが出来る。\r
117  * @name MiMicException.3\r
118  * @function\r
119  * @param {object} e\r
120  * eのクラスにより、動作が異なる。\r
121  * <ul>\r
122  * <li>{MiMicErrorCode} - エラーコードを指定して例外を生成する。</li>\r
123  * <li>{MiMicException} - codeとmessageを継承して例外を生成する。コールスタックを生成するときは、このパターンを使うこと。</li>\r
124  * </ul>\r
125  * @param {string} s\r
126  * 追加するエラーメッセージ。\r
127  */\r
128 /**\r
129  * MiMic javascript APIが生成する例外クラスのコンストラクタである。関数ごとにMiMicExceptionを使ったtry-catchを導入することにより、例外発生時にスタックトレースメッセージを得ることが出来る。\r
130  * スタックトレースは改行で連結された文字列である。messageプロパティに格納される。alert関数で表示することで、効率的なデバックが可能である。\r
131  * 引数の違いにより、数種類の呼び出し方がある。\r
132  * @constructor\r
133  * @param ...\r
134  * 詳細は、MiMicException.nを参照。\r
135  */\r
136 function MiMicException(/*...*/)\r
137 {\r
138         var pfx;\r
139         if(typeof arguments.callee.caller=="function"){\r
140                  if(arguments.callee.caller.name.toString().length>0){\r
141                         pfx="function '"+arguments.callee.caller.name+'.';\r
142                  }else{\r
143                         var s=arguments.callee.caller.toString();\r
144                         pfx="closure '"+s.substring(0,s.indexOf("{"))+"...'";\r
145                  }\r
146         }else{\r
147                 pfx="root document";\r
148         }\r
149         var sfx="";\r
150         switch(arguments.length){\r
151         case 0:\r
152                 //とりあえずexceptiion\r
153                 this.code=MiMicError.NG[0];\r
154                 this.message=pfx+" code(0x"+this.code.toString(16)+")"+MiMicError.NG[1];\r
155                 return;\r
156         case 1:\r
157                 var v=arguments[0];\r
158                 if(v instanceof MiMicException){\r
159                         //exception継承\r
160                         this.code=v.code;\r
161                         sfx="  \nfrom "+v.message;\r
162                 }else if(typeof v=="object" && v.length==2){\r
163                         //Errorコードテーブル\r
164                         this.code=v[0];\r
165                         sfx=v[1];\r
166                 }else{\r
167                         //文字列やオブジェクト\r
168                         this.code=MiMicError.NG[0];\r
169                         sfx=MiMicError.NG[1]+(((typeof v)!='undefined')?v.toString():"v==undefined");\r
170                 }\r
171                 this.message=pfx+" code(0x"+this.code.toString(16)+")"+sfx;\r
172                 return;\r
173         case 2:\r
174                 var v=arguments[0];\r
175                 if(v instanceof MiMicException){\r
176                         //Exception+メッセージ\r
177                         this.code=v.code;\r
178                         this.message=pfx+" code(0x"+this.code.toString(16)+")"+"\nfrom "+v.message+":"+arguments[1];\r
179                         return;\r
180                 }else if(typeof v!="string" && v.length==2){\r
181                         //Errorコードテーブル+メッセージ\r
182                         this.code=v[0];\r
183                         this.message=pfx+" code(0x"+this.code.toString(16)+")"+v[1]+":"+arguments[1];\r
184                 }else{\r
185                         break;\r
186                 }\r
187                 return;\r
188         default:\r
189                 break;\r
190         }\r
191         throw new MiMicException("Invalid MiMicException argument.");\r
192 }\r
193 \r
194 MiMicException.prototype={\r
195         /**\r
196          * MiMicErrorCode形式のエラーコードを保持する。\r
197          * @field {object as MiMicErrorCode}
198          */\r
199         code:MiMicError.OK,\r
200         /**\r
201          * エラーメッセージを保持する。この値は、改行区切りのコールスタックである。\r
202          * @field {string}
203          */\r
204         message:"",\r
205         /**\r
206          * messageフィールドをalertで表示する。\r
207          * @function\r
208          * @example\r
209          * try{\r
210          *      throw new MiMicException();\r
211          * }catch(e){\r
212          *      e.alert();\r
213          * }     
214          */\r
215         alert:function(){\r
216                 alert(this.message);\r
217         },\r
218         /**\r
219          * toStringを上書きする。オブジェクトを文字列化する。\r
220          * 文字列は例外のコールスタックであり、デバックで役立つ。\r
221          * @function\r
222          * @return {string}\r
223          * 現在のオブジェクトの状態(例外のコールスタック)\r
224          * @example\r
225          * try{\r
226          *      throw new MiMicException();\r
227          * }catch(e){\r
228          *      alert(e.toString());\r
229          * }     
230          */\r
231         toString:function()\r
232         {\r
233                 return "MiMicException:"+this.message;\r
234         }       \r
235 }\r
236 \r
237 \r
238 \r
239 \r
240 \r
241 \r
242 /*\r
243  * MiMicRemoteMCU
244  */\r
245 var MiMicRemoteMcuInterface;\r
246 \r
247 (function(){\r
248         /**\r
249          * エラーID定義\r
250          * @private
251          */\r
252         var EE=function(i_base)\r
253         {\r
254                 return {\r
255                 NG:[i_base|0x00,"Unknown exception in MiMicRemoteMcuInterface"],\r
256                 TCP_CONNECT:[i_base|0x01,"TCP CONNECT FAILED"],//接続エラー\r
257                 HTTP       :[i_base|0x02,"HTTP FAILED"]}//HTTPエラー\r
258         }(MiMicError.NG[0]|MiMicError.MID_MiMic|MiMicError.CAID_RemoteMCU);\r
259         /**\r
260          * MiMicRemoteMcuInterfaceクラスのコンストラクタ。\r
261          * MiMicRemoteMcuInterfaceクラスは、MCUで動作するMiMicRemoteMcuとの通信機能と、接続状態の監視機能を提供する。低レベルAPI全てを実装する。\r
262          * 低レベルAPIは、MiMicRemoteMcuとの通信を、関数コールに変換する。\r
263          * インスタンス生成直後は、MiMicRemoteMcuとの接続は断状態である。connect関数を実行して、接続する必要がある。\r
264          * 通信仕様については、MiMicVM.pdf Appendix 1.MiMicVM HTTP Interfaceを参照すること。\r
265          * @constructor\r
266          * @param {string} server\r
267          * 接続するMiMicRemoteMcuのホストアドレスを指定する。IPアドレス、ホスト名等。\r
268          * ex. “127.0.0.1” , “127.0.0.1:3939”\r
269          * @example\r
270          * //create a controlable MCU via network.\r
271          * var mcu=new MiMicRemoteMcuInterface(“192.168.0.39”);      
272          */\r
273         MiMicRemoteMcuInterface=function MiMicRemoteMcuInterface(server)\r
274         {\r
275                 this._mimic_host=server;\r
276         }\r
277 \r
278         MiMicRemoteMcuInterface.prototype=\r
279         {\r
280                 _mimic_host:null,\r
281                 _keep_alive:null,       \r
282                 /**\r
283                  * XmlHttpRequestを実行する。\r
284                  * @private\r
285                  * @return\r
286                  * 取得したデータ。\r
287                  * @throws\r
288                  * 取得失敗時(例外発生の場合)\r
289                  */\r
290                 _xhrGet:function(i_url,i_async,i_callback)\r
291                 {\r
292                     var xhr = window.XDomainRequest ? new XDomainRequest() : new XMLHttpRequest();\r
293                     var prog=0;\r
294                     try{\r
295                         if(i_async){\r
296                                 xhr.onreadystatechange = function(){\r
297                                                 if (xhr.readyState == 4){\r
298                                                         i_callback(xhr);        \r
299                                                 }\r
300                                         }\r
301                                 }\r
302                         xhr.open("GET",i_url,i_async);\r
303                         prog=1;\r
304                         xhr.send(null); \r
305                         prog=2;\r
306                     } catch (e){\r
307                         throw new MiMicException(\r
308                                 function(){\r
309                                         switch(prog){\r
310                                         case 1:return EE.HTTP;\r
311                                         }\r
312                                                 return EE.TCP_CONNECT;\r
313                                         }(),"url="+i_url);\r
314                     }\r
315                     return xhr;\r
316                 },\r
317                 /**\r
318                  * MiMicの応答から、オンラインチェックを実行します。\r
319                  * @private\r
320                  * @param res\r
321                  * レスポンスを格納済みのXHRオブジェクト\r
322                  * @return\r
323                  * オンラインならtrue\r
324                  * 入力文章から状態が判定できなかった場合、false\r
325                  */\r
326                 _isOnline_parseResponse: function(res)\r
327                 {\r
328                         try{\r
329                                 if(res.status!=200){\r
330                                         return false;\r
331                                 }\r
332                                 var ret=eval("("+res.responseText+")");\r
333                                 if(ret.application.split(";")[0]!="MiMicRemoteMCU/1.0a"){\r
334                                         return false;\r
335                                 }\r
336                         }catch(e){\r
337                                 return false;\r
338                         }\r
339                         return true;\r
340                 },\r
341                 /**\r
342                  * MvmのレスポンスをJSOにする。\r
343                  * @private\r
344                  * @return\r
345                  * 成功時はjson\r
346                  * @throws\r
347                  * JSONが得られない場合\r
348                  */\r
349                 _parseMvmResult:function(i_mvmresult)\r
350                 {\r
351                         var ret=eval("("+i_mvmresult+")");\r
352                         if(ret.version=="MiMicVM/1.0a;Json/1.0"){\r
353                                 if(ret.result!=undefined){\r
354                                         if(ret.result!=0x0 || ret.stream!=undefined){\r
355                                                 return ret;\r
356                                         }\r
357                                 }\r
358                         }\r
359                         //なんかうまくいかない。\r
360                         throw new MiMicException(EE.NG);\r
361                 },\r
362                 /**\r
363                  * 接続状態を真偽値で返す。\r
364                  * 接続状態の場合、execBc等の低レベルAPIを使用できる。\r
365                  * 状態は、インスタンスが定期的に実行するプローブ信号でチェックされ、更新される。\r
366                  * @function\r
367                  * @return {boolean}\r
368                  * 接続状態。trueなら、MCUインタフェイスは利用可能。\r
369                  * @example\r
370                  * //show connection status\r
371                  * var mri=new  MiMicRemoteMcuInterface(“192.168.0.1”);\r
372                  * alert(mri.isConnected());             
373                  */\r
374                 isConnected:function isConnected()\r
375                 {\r
376                         return this._keep_alive!=null;\r
377                 },\r
378                 /**\r
379                  * 接続中のMiMicremoteMCUへ、整形済みのMiMicBCを送信する。\r
380                  * 関数の利用前に、connect関数でMiMicremoteMCUへ接続する必要がある。\r
381                  * 何らかのエラーが発生してMiMicRemoteMCUからの応答が得られない場合、関数は例外を発生する。\r
382                  * この状況は、TCP/IPエラー、HTTPエラー、HTTPステータスエラー、MiMicVMのラインタイムエラー、MiMicRemoteMCUのフォールト等の原因で発生する。<br/>\r
383                  * 関数は同期実行でのため、RemoteMCUが応答しないと制御がブロックする。非同期関数は今後実装する。\r
384                  * @function\r
385                  * @param {string} i_bc\r
386                  * 整形済みのMiMicBC文字列。MiMicBCについては、MiMicVM.pdf の、MiMicBCの章を参照。\r
387                  * @return\r
388                  * MiMicVMのパース済みJavascriptObjectである。\r
389                  * 形式は以下の通り。\r
390                  * <pre>\r
391                  * {version: string,result: int,stream int[]}\r
392                  * </pre>\r
393                  * 詳細は、 MiMicVM.pdf Appendix 1. MiMicVM HTTP Interfaceを参照。\r
394                  * @example\r
395                  * //execute NOP.\r
396                  * var mri=new  MiMicRemoteMcuInterface(“192.168.0.1”);\r
397                  * mri.connect(function(){});\r
398                  * mri.execBc(“ZAZZ.E”);//NOP;EXIT;          \r
399                  */\r
400                 execBc:function execBc(i_bc)\r
401                 {\r
402                         try{\r
403                                 var res=this._xhrGet("http://"+this._mimic_host+"/mvm.api?v=1&bc="+i_bc,false);\r
404                                 if(res.status!=200){\r
405                                         throw new MiMicException(EE.HTTP,"i_bc="+i_bc+",XHR.status="+res.status);\r
406                                 }\r
407                                 return this._parseMvmResult(res.responseText,false);\r
408                         }catch(e){\r
409                                 throw new MiMicException(e);\r
410                         }\r
411                 },\r
412 \r
413                 /**\r
414                  * MiMicRemoteMCUへ接続する。\r
415                  * 既に接続済みの場合は何もしない。\r
416                  * @function\r
417                  * @param {function} i_callback\r
418                  * 回線状態を定期的に通知するコールバックハンドラ。\r
419                  * <pre>function(b:{boolean})</pre>\r
420                  * disconnect関数を呼び出すまでの間、回線の状態を定期的に受け取る。\r
421                  * bは接続状態を表す真偽値である。trueの時、接続中である。falseの場合、外部要因により切断されている。\r
422                  * falseが通知されるのは、disconnectが呼び出されるまでに非同期切断を検出したときだけである。disconnectで切断した場合には呼び出されない。           \r
423                  * @example\r
424                  * //show connection status\r
425                  * var mri=new  MiMicRemoteMcuInterface(“192.168.0.1”);\r
426                  * mri.connect(function(b){if(!b){alert(“disconnected!”);}});                \r
427                  */\r
428                 connect:function connect(i_callback)\r
429                 {\r
430                         try{\r
431                                 var _t=this;\r
432                                 //接続中ならおわり\r
433                                 if(this._keep_alive!=null){\r
434                                         return;\r
435                                 }\r
436                                 var res=this._xhrGet("http://"+this._mimic_host+"/status.api",false,null);\r
437                                 function startCheck()\r
438                                 {\r
439                                         function checkProc(res)\r
440                                         {\r
441                                                 //結果の確認\r
442                                                 if(!_t._isOnline_parseResponse(res)){\r
443                                                         if(_t._keep_alive!=null){\r
444                                                                 _t._keep_alive=null;\r
445                                                                 i_callback(false);\r
446                                                         }\r
447                                                 }else{\r
448                                                         i_callback(true);\r
449                                                         startCheck();\r
450                                                 }\r
451                                                 return;\r
452                                         }\r
453                                         _t._keep_alive={\r
454                                                 tid:setTimeout(function(){_t._keep_alive.xhr=_t._xhrGet("http://"+_t._mimic_host+"/status.api",true,checkProc);},5000),\r
455                                                 xhr:null};\r
456                                 };\r
457                                 //非同期監視の開始\r
458                                 startCheck();\r
459                         }catch(e){\r
460                                 throw new MiMicException(e);\r
461                         }\r
462                         return;\r
463                 },\r
464                 /**\r
465                  * 接続中のMiMicRemoteMCUから切断する。接続されていなければ何もしない。\r
466                  * @function\r
467                  * @example\r
468                  * //connect and disconnect\r
469                  * var mri=new  MiMicRemoteMcuInterface(“192.168.0.1”);\r
470                  * mri.connect(function(b){if(!b){alert(“disconnected!”);}});\r
471                  * mri.disconnect();             \r
472                  */\r
473                 disconnect:function disconnect()\r
474                 {\r
475                         try{\r
476                                 if(this._keep_alive!=null){\r
477                                         clearTimeout(this._keep_alive.tid);\r
478                                         var xhr=this._keep_alive.xhr;\r
479                                         this._keep_alive=null;//abortによるコールバックを抑制\r
480                                         if(xhr!=null){\r
481                                                 xhr.abort();\r
482                                         }\r
483                                 }\r
484                         }catch(e){\r
485                                 throw new MiMicException(e);\r
486                         }\r
487                 }\r
488         }\r
489         \r
490         \r
491         \r
492         \r
493         \r
494 }());\r
495 \r
496 \r
497 \r