source: uKadecot/trunk/tools/EcnlControllerUI/EcnlControllerUI/CtrlUI.cs@ 101

Last change on this file since 101 was 101, checked in by coas-nagasima, 9 years ago

TOPPERS/uKadecotのソースコードを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/plain
File size: 36.7 KB
RevLine 
[101]1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2015 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id: CtrlUI.cs 101 2015-06-02 15:37:23Z coas-nagasima $
36 */
37
38using System;
39using System.Collections;
40using System.Collections.Generic;
41using System.Diagnostics;
42using System.Html;
43using System.Linq;
44using System.Net.WebSockets;
45using System.Serialization;
46using System.Text;
47using System.Text.RegularExpressions;
48using System.Web;
49using System.Xml;
50using control;
51using ctrlui;
52using jQueryApi;
53using Kadecot;
54
55public class CtrlUI
56{
57 public static CtrlUI Page;
58 public static Information Info;
59
60 public static void Main()
61 {
62 if (Page == null) {
63 Page = new CtrlUI();
64 Info = new Information();
65 }
66
67 jQuery.Document.On("pageinit", "#index", Page.InitClassGroups);
68 }
69
70 private static Element page;
71 private Dictionary<DeviceController.DeviceInfo, DeviceController.DeviceInfo> Read = new Dictionary<DeviceController.DeviceInfo, DeviceController.DeviceInfo>();
72
73 public static Element GetPage(Element ele)
74 {
75 var page = ele;
76 if (jQuery.Select(page).Is("[data-role=\"page\"]")) {
77 return page;
78 }
79 if (jQuery.Select(page).Parents("[data-role=\"page\"]").Length == 1) {
80 return jQuery.Select(page).Parents("[data-role=\"page\"]").GetElement(0);
81 }
82 return null;
83 }
84
85 /// <summary>クラスグループ(ClassGroupList.json)</summary>
86 static JsonClassGroupInfo[] m_ClassGroups;
87
88 /// <summary>クラス</summary>
89 static JsonClassInfo m_ProfileClassInfo;
90 static List<JsonClassInfo> m_Classes;
91
92 WampClient m_WampClient;
93 /// <summary>現在接続中の機器</summary>
94 DeviceController m_DeviceController;
95
96 private DeviceController.DeviceInfo _m_CurrentNode;
97
98 /// <summary>現在選択中のノード</summary>
99 DeviceController.DeviceInfo m_CurrentNode
100 {
101 get { return _m_CurrentNode; }
102 set
103 {
104 bool flag = (_m_CurrentNode != value) || (_m_CurrentNode == null && value == null);
105 _m_CurrentNode = value;
106
107 if (flag)
108 jQuery.Document.Trigger(UIEventNames.CurrentNodeChange);
109 }
110 }
111
112 /// <summary>
113 /// コンストラクタ
114 /// </summary>
115 public CtrlUI()
116 {
117 m_WampClient = new WampClient();
118 m_WampClient.addOpenCallback(WampClientConnected);
119 m_WampClient.addCloseCallback(WampClientDisconnected);
120 m_WampClient.connect("ws://" + Window.Location.Host + "/webapi.ashx");
121 }
122
123 /// <summary>
124 /// #indexページ読み込み時に実行
125 /// </summary>
126 /// <param name="ele"></param>
127 /// <param name="ev"></param>
128 private void InitClassGroups(jQueryEvent eve)
129 {
130 page = eve.Target;
131 SetEvent();
132
133 if (m_ClassGroups != null)
134 return;
135
136 DeviceController.GetClassInfo = GetClassInfoHandler;
137 m_CurrentNode = null;
138 string ClassGroupListUrl = "devices/ClassGroupList.json";
139 jQuery.Ajax(ClassGroupListUrl).Success(InitClassGroups).Error(
140 (request, textStatus, error) => {
141 AjaxError(request, textStatus, error, ClassGroupListUrl);
142 });
143 }
144
145 private void SetEvent()
146 {
147 jQuery.Document.On(UIEventNames.LoadingShow, UIEventHandler.LoadingShow);
148 jQuery.Document.On(UIEventNames.LoadingHide, UIEventHandler.LoadingHide);
149 jQuery.Document.On(UIEventNames.CurrentNodeChange, this.CurrentNodeChange);
150 jQuery.Document.On(UIEventNames.SearchStart, this.SearchStart);
151 jQuery.Document.On(UIEventNames.SearchEnd, this.SearchEnd);
152 jQuery.Document.On(UIEventNames.SearchError, this.SearchError);
153 jQuery.Document.On(UIEventNames.PropertyWriteStart, this.PropertyWriteStart);
154 jQuery.Document.On(UIEventNames.PropertyWriteEnd, this.PropertyWriteEnd);
155 ConnectionSwt.Change(Connect);
156 SetPropertyBtn.Click(SetProperty);
157 GetPropertyBtn.Click(GetProperty);
158 SetGetPropertyBtn.Click(SetGetProperty);
159 KadecotBtn.Click(KadecotClick);
160 PropertyList.Change(PropertyChange);
161 SetInitParamsBtn.Click(SetInitParams);
162 }
163
164 /// <summary>
165 /// "devices/ClassGroupList.json"ファイルの読み込みに成功したとき実行します
166 /// </summary>
167 /// <param name="data">ファイルのデータ</param>
168 private void InitClassGroups(object data)
169 {
170 List<JsonClassGroupInfo> classGroups = data.ToJSClassGroupInfoList();
171 //初期化
172 m_Classes = new List<JsonClassInfo>();
173 m_ClassGroups = classGroups.ToArray();
174 GetClassInfoHandler(T_ECN_EOJ.X1_PROFILE, T_ECN_EOJ.X2_NODE_PROFILE, GetClassInfoCallback);
175 }
176
177 /// <summary>
178 /// コールバック関数
179 /// </summary>
180 /// <param name="di"></param>
181 private void GetClassInfoCallback(JsonClassInfo di)
182 {
183 m_ProfileClassInfo = di;
184 }
185
186 /// <summary>
187 /// devices/ClassListxx.jsonファイルの読み込み
188 /// </summary>
189 /// <param name="x1">クラスグループコード</param>
190 /// <param name="x2">クラスコード</param>
191 /// <param name="cb">コールバック関数</param>
192 private void GetClassInfoHandler(byte x1, byte x2, DeviceController.GetClassInfoCallback cb)
193 {
194 JsonClassInfo eclass = m_Classes.FirstOrDefault(p => (p.classGroup.classGroupCode == x1) && (p.classCode == x2));
195
196 //すでにjsonファイルが読み込まれているので、ファイルを読み込まない。
197 if (eclass != null) {
198 if (eclass.properties == null)
199 GetPropertyList(eclass, cb);
200 else
201 cb(eclass);
202 return;
203 }
204 //eclass==nullの場合
205 JsonClassGroupInfo classGroup = m_ClassGroups.FirstOrDefault(p => (p.classGroupCode == x1));
206
207 string classListUrl = "devices/ClassList" + x1.ToString("X2").ToUpper() + ".json";
208
209 jQuery.Ajax(classListUrl).Success((data) => {
210 Debug.WriteLine(classListUrl + "読み込み成功");
211 GetClassInfoSuccess(data, x1, x2, classGroup, cb);
212 }).Error((request, textStatus, error) => {
213 Debug.WriteLine(classListUrl + "読み込み失敗");
214 GetClassInfoError(request, textStatus, error, eclass, cb, classListUrl);
215 });
216 }
217
218 /// <summary>
219 /// devices/ClassListxx.jsonファイルの取得に成功した時実行します。
220 /// </summary>
221 /// <param name="data"></param>
222 private void GetClassInfoSuccess(object data, byte x1, byte x2, JsonClassGroupInfo classGroup, DeviceController.GetClassInfoCallback cb)
223 {
224 List<JsonClassInfo> classes = data.ToJSClassInfoList(classGroup);
225 m_Classes.AddRange(classes);
226 JsonClassInfo eclass = m_Classes.FirstOrDefault(p => (p.classGroup.classGroupCode == x1) && (p.classCode == x2));
227 GetPropertyList(eclass, cb);
228 }
229
230 /// <summary>
231 /// devices/PropertyListxxxx.jsonファイルの取得
232 /// </summary>
233 /// <param name="data"></param>
234 private void GetPropertyList(JsonClassInfo eclass, DeviceController.GetClassInfoCallback cb)
235 {
236 string PropertyListUrl = "devices/PropertyList" + eclass.classGroup.classGroupCode.ToString("X2").ToUpper() + eclass.classCode.ToString("X2").ToUpper() + ".json";
237 Debug.WriteLine(PropertyListUrl + "読み込み");
238
239 jQuery.Ajax(PropertyListUrl).Success((data1) => {
240 Debug.WriteLine(PropertyListUrl + "読み込み成功");
241 GetPropertyListSuccess(data1, eclass);
242 }).Error((request, textStatus, error) => {
243 Debug.WriteLine(PropertyListUrl + "読み込み失敗");
244 PropertyListAjaxError(request, textStatus, error, eclass, cb, PropertyListUrl);
245 }).Complete((request, textStatus) => {
246 GetPropertyListComplete(request, textStatus, eclass, cb);
247 });
248 }
249
250 /// <summary>
251 /// devices/PropertyListxxxx.jsonファイルの取得に成功
252 /// </summary>
253 /// <param name="data"></param>
254 private void GetPropertyListSuccess(object data, JsonClassInfo eclass)
255 {
256 List<JsonPropertyInfo> properties = data.ToJSPropertyInfoList();
257 eclass.properties = properties.ToArray();
258 }
259
260 /// <summary>
261 /// devices/PropertyListxxxx.jsonファイルの取得後の処理
262 /// </summary>
263 /// <param name="request"></param>
264 /// <param name="textStatus"></param>
265 private void GetPropertyListComplete(jQueryXmlHttpRequest request, string textStatus, JsonClassInfo eclass, DeviceController.GetClassInfoCallback cb)
266 {
267 if (request.StatusText.Equals("OK")) {
268 cb(eclass);
269 }
270 }
271
272 /// <summary>
273 /// devices/ClassListxx.jsonファイルがなかった場合
274 /// </summary>
275 /// <param name="request"></param>
276 /// <param name="textStatus"></param>
277 /// <param name="error"></param>
278 private void GetClassInfoError(jQueryXmlHttpRequest request, string textStatus, Exception error,
279 JsonClassInfo eclass, DeviceController.GetClassInfoCallback cb, string url)
280 {
281 AjaxError(request, textStatus, error, url);
282 cb(eclass);
283 }
284
285 /// <summary>
286 /// PropertyListxxxx.jsonファイル読み込みエラー
287 /// </summary>
288 /// <param name="request"></param>
289 /// <param name="textStatus"></param>
290 /// <param name="error"></param>
291 private void PropertyListAjaxError(jQueryXmlHttpRequest request, string textStatus, dynamic error, JsonClassInfo eclass, DeviceController.GetClassInfoCallback cb, string url)
292 {
293 string PropertyListBaseUrl = "devices/PropertyListBase.json";
294 jQuery.Ajax(PropertyListBaseUrl).Success((data1) => {
295 Debug.WriteLine(PropertyListBaseUrl + "読み込み成功");
296 GetPropertyListSuccess(data1, eclass);
297 }).Error((request1, textStatus1, error1) => {
298 Debug.WriteLine(PropertyListBaseUrl + "読み込み失敗");
299 AjaxError(request1, textStatus1, error1, url);
300 }).Complete((request1, textStatus1) => {
301 GetPropertyListComplete(request1, textStatus1, eclass, cb);
302 });
303 }
304
305 /// <summary>
306 ///
307 /// </summary>
308 private void sendHello()
309 {
310 m_WampClient.sendHello("default", "{\"roles\":{\"caller\":{},\"subscriber\":{}}}", OnWelcom);
311 }
312
313 private void OnWelcom(object args)
314 {
315 m_WampClient.sendSubscribe("{}", "com.sonycsl.kadecot.echonetlite.topic.GeneralLighting.OperationStatus", OnSubscribed, OnSubscribed);
316 }
317
318 private void OnSubscribed(object args)
319 {
320 }
321
322 /// <summary>
323 /// 機器検索ボタンを押下したとき実行
324 /// </summary>
325 /// <param name="args"></param>
326 private void OnDevListed(object args)
327 {
328 int cmd = (int)((dynamic[])args)[0];
329 if (cmd != (int)WAMP_MSG_TYPE.RESULT) {
330 jQuery.Document.Trigger(UIEventNames.SearchError);
331 return;
332 }
333
334 //初期化
335 List<WampApiKadecotDevice> alldevs = args.GetAllDevices();
336 GetDeviceInfo(alldevs, 0, new List<DeviceController.NodeInfo>());
337 }
338
339 /// <summary>
340 /// 接続されている機器の設定値を取得
341 /// </summary>
342 /// <param name="alldevs"></param>
343 /// <param name="pos"></param>
344 private void GetDeviceInfo(List<WampApiKadecotDevice> alldevs, int pos, List<DeviceController.NodeInfo> m_NodeList)
345 {
346 WampApiKadecotDevice device = alldevs[pos];
347
348 WampClientCore.WampCallbackArgs callback = (args) => {
349 int cmd = (int)((dynamic[])args)[0];
350 if (cmd != (int)WAMP_MSG_TYPE.RESULT) {
351 jQuery.Document.Trigger(UIEventNames.SearchError);
352 return;
353 }
354
355 WebApiObjectInfo dev = new WebApiObjectInfo(device.deviceId, ((dynamic[])args)[4], false);
356
357 GetClassInfoHandler(dev.x1, dev.x2, (dc) => {
358 DeviceController.DeviceInfo di = dc.GetDeviceInfo(dev, device);
359 DeviceController.NodeInfo node = m_NodeList.FirstOrDefault((ni) => { return (string)ni.Data == device.ip_addr; });
360 if (node == null) {
361 var profile = new DeviceController.DeviceInfo(m_ProfileClassInfo, true, T_ECN_EOJ.X1_PROFILE, T_ECN_EOJ.X2_NODE_PROFILE, 1, dev.enodid);
362 node = new DeviceController.NodeInfo((ENOD_ID)dev.enodid, profile);
363 node.Data = device.ip_addr;
364 m_NodeList.Add(node);
365 }
366 node.Devices.Add(di);
367
368 pos++;
369 if (pos < alldevs.Count) {
370 GetDeviceInfo(alldevs, pos, m_NodeList);
371 }
372 else {
373 jQuery.Document.Trigger(UIEventNames.SearchEnd);
374 m_DeviceController = new DeviceController(m_NodeList);
375 UpdateUI();
376 }
377 });
378 };
379
380 if (device.protocol == "arduino") {
381 var arg = new
382 {
383 x1 = 0x0E,
384 x2 = 0xF0,
385 x3 = 0x01,
386 enodid = 0x01,
387 properties = new[] {
388 new{epc = 0x00, flag = "RULE_SET,RULE_GET", size = 0x01},
389 new{epc = 0x01, flag = "RULE_SET,RULE_GET", size = 0x01},
390 new{epc = 0x02, flag = "RULE_SET,RULE_GET", size = 0x01},
391 new{epc = 0x03, flag = "RULE_SET,RULE_GET", size = 0x01},
392 new{epc = 0x04, flag = "RULE_SET,RULE_GET", size = 0x01},
393 new{epc = 0x05, flag = "RULE_SET,RULE_GET", size = 0x01},
394 new{epc = 0x06, flag = "RULE_SET,RULE_GET", size = 0x01},
395 new{epc = 0x07, flag = "RULE_SET,RULE_GET", size = 0x01},
396 new{epc = 0x08, flag = "RULE_SET,RULE_GET", size = 0x01},
397 new{epc = 0x09, flag = "RULE_SET,RULE_GET", size = 0x01},
398 new{epc = 0x0A, flag = "RULE_SET,RULE_GET", size = 0x01},
399 new{epc = 0x0B, flag = "RULE_SET,RULE_GET", size = 0x01},
400 new{epc = 0x0C, flag = "RULE_SET,RULE_GET", size = 0x01},
401 new{epc = 0x0D, flag = "RULE_SET,RULE_GET", size = 0x01},
402 new{epc = 0x0E, flag = "RULE_GET", size = 0x01},
403 new{epc = 0x0F, flag = "RULE_GET", size = 0x01},
404 new{epc = 0x10, flag = "RULE_GET", size = 0x01},
405 new{epc = 0x11, flag = "RULE_GET", size = 0x01},
406 new{epc = 0x12, flag = "RULE_GET", size = 0x01},
407 new{epc = 0x13, flag = "RULE_GET", size = 0x01},
408 }
409 };
410 callback(new object[] { 50, 0, new { deviceId = 1 }, new object[0], arg });
411 }
412 else {
413 m_WampClient.sendCall("{\"deviceId\":" + device.deviceId + "}", "jp.toppers.ecnl.procedure.getDeviceInfo", null, null, callback);
414 }
415 }
416
417 /// <summary>
418 /// ノードリストを更新
419 /// </summary>
420 private void UpdateUI()
421 {
422 if (NodeList == null)
423 return;
424 NodeList.Html("");
425 NodeList.Append(m_DeviceController.GetUINodeList(listitem_Click));
426 NodeList.CollapsibleSet().CollapsibleSet("refresh");
427 jQuery.Select("ul[data-role='listview']", NodeList).ListView().ListView("refresh");
428 }
429
430 /// <summary>
431 /// コールバック関数
432 /// </summary>
433 /// <param name="args"></param>
434 private void OnResponse(object args)
435 {
436 int switchData = (int)((dynamic[])args)[0];
437 if (switchData != (int)WAMP_MSG_TYPE.RESULT) {
438 return;
439 }
440
441 dynamic doc = ((dynamic[])args)[4];
442 if (m_DeviceController != null) {
443 m_DeviceController.RecvResponse(new WebApiEchonetMessage(doc));
444 if (PropertyList == null)
445 return;
446
447 m_CurrentNode.GetData();
448 }
449 SetPropertyBtn.Disable(true);
450 }
451
452 private void OnSetResponse(object args)
453 {
454 dynamic doc = ((dynamic[])args)[4];
455 if (m_DeviceController != null) {
456 if (PropertyList == null)
457 return;
458 m_DeviceController.RecvResponse(new WebApiEchonetMessage(doc));
459 }
460 SetPropertyBtn.Disable(true);
461 }
462
463 /// <summary>
464 /// #li_device_XXXXXXをクリックしたとき
465 /// </summary>
466 /// <param name="elem"></param>
467 /// <param name="ev"></param>
468 private void listitem_Click(Element elem, jQueryEvent ev, DeviceController.DeviceInfo di)
469 {
470 if (PropertyList == null)
471 return;
472 m_CurrentNode = di;
473 }
474
475 /// <summary>
476 /// webapiと接続された時、機器検索のアイコンを切り替える
477 /// </summary>
478 private void WampClientConnected()
479 {
480 //接続スイッチがOFFの時、スイッチを切り替える
481 bool flag = ConnectionSwt.Prop("checked");
482 if (!flag) {
483 ConnectionSwt.Prop("checked", true).FlipSwitch("refresh");
484 }
485 SearchBtn.ToggleClass("ui-icon-alert", "ui-icon-refresh");
486 sendHello();
487 }
488
489 /// <summary>
490 /// webapiと切断されたとき、機器検索のアイコンを切り替える
491 /// </summary>
492 private void WampClientDisconnected()
493 {
494 SearchBtn.ToggleClass("ui-icon-refresh", "ui-icon-alert");
495 }
496
497 /// <summary>
498 /// 接続スイッチを変更
499 /// </summary>
500 /// <param name="ele"></param>
501 public void Connect(Element ele, jQueryEvent eve)
502 {
503 bool connect = jQuery.Select(ele).Prop("checked");
504
505 //接続スイッチがOn && m_WampClient.isConnecting() == false
506 if (connect && !m_WampClient.isConnecting()) {
507 Debug.WriteLine("m_WampClient.isConnecting():" + m_WampClient.isConnecting().ToString());
508 m_WampClient.connect("ws://" + Window.Location.Host + "/webapi.ashx");
509 }
510 //接続スイッチがOff && m_WampClient.isConnecting() ==true
511 else if (!connect && m_WampClient.isConnecting()) {
512 m_WampClient.disconnect();
513 // m_WampClient.sendGoodbye("{}", "wamp.error.system_shutdown",Disconnect);
514 }
515 }
516
517 /// <summary>
518 /// 切断
519 /// </summary>
520 /// <param name="args"></param>
521 public void Disconnect(object args)
522 {
523 m_WampClient.disconnect();
524 }
525
526 int TimerId = 0;
527
528 /// <summary>
529 /// 機器検索ボタンを押下
530 /// </summary>
531 /// <param name="ele"></param>
532 public void Search(Element ele, jQueryEvent ev)
533 {
534 jQuery.Document.Trigger(UIEventNames.SearchStart);
535 string data = m_WampClient.sendCall("{}", "com.sonycsl.kadecot.provider.procedure.getDeviceList",
536 null, null, OnDevListed);
537 if (data == null) {
538 jQuery.Document.Trigger(UIEventNames.SearchError);
539 return;
540 }
541 this.TimerId = Window.SetInterval(() => {
542 jQuery.Document.Trigger(UIEventNames.SearchError);
543 }, 20000);
544 }
545
546 public void SearchStart(jQueryEvent ev)
547 {
548 jQueryMobile.Loading("show", new LoadingOption("機器検索中...", true));
549 SearchBtn.Disable(true);
550 Debug.WriteLine("機器検索開始");
551 }
552
553 /// <summary>
554 /// 機器が見つかった時実行
555 /// </summary>
556 /// <param name="ev"></param>
557 public void SearchEnd(jQueryEvent ev)
558 {
559 if (this.TimerId != 0) {
560 Window.ClearInterval(this.TimerId);
561 this.TimerId = 0;
562 }
563
564 jQueryMobile.Loading("hide");
565 SearchBtn.Disable(false);
566 NodeList.Find("li .ui-icon-alert").ToggleClass("ui-icon-alert", "ui-icon-carat-r");
567
568 Debug.WriteLine("機器検索終了");
569 }
570
571 /// <summary>
572 /// 機器が見つからなかったとき実行
573 /// </summary>
574 /// <param name="ev"></param>
575 public void SearchError(jQueryEvent ev)
576 {
577 if (this.TimerId != 0) {
578 Window.ClearInterval(this.TimerId);
579 this.TimerId = 0;
580 }
581
582 jQueryMobile.Loading("hide");
583 jQuery.Select("#bt_search").RemoveAttr("disabled");
584 Debug.WriteLine("機器検索エラー");
585 Window.Alert("機器が見つかりませんでした");
586 NodeList.Find("li .ui-icon-carat-r").ToggleClass("ui-icon-carat-r", "ui-icon-alert");
587 }
588
589 public void PropertyWriteStart(jQueryEvent ev)
590 {
591 jQueryMobile.Loading("show");
592 }
593
594 public void PropertyWriteEnd(jQueryEvent ev)
595 {
596 //PropertyList.Find("li").Find(".ui-field-contain").Children(".ui-input-text").Each((i, ele) => {
597 // if (jQuery.Select(ele).Children(".ui-input-text").Length > 0) {
598 // jQuery.Select(ele).Children("a").Remove();
599 // jQuery.Select(ele).Children(".ui-input-text").Unwrap();
600 // }
601 //});
602 jQueryMobile.Loading("hide");
603 }
604
605 /// <summary>
606 /// 設定ボタンを押下
607 /// </summary>
608 /// <param name="ele"></param>
609 public void SetProperty(Element ele, jQueryEvent eve)
610 {
611 WebApiSet esv = new WebApiSet();
612 jQueryObject ctrls = PropertyList;
613
614 esv.deojid = (ENOD_ID)m_CurrentNode.EObjId;
615 bool enable = false;
616
617 foreach (var dpi in m_CurrentNode.Properties) {
618 if (dpi.InputData == null) {
619 continue;
620 }
621 else if (dpi.IsWaitRes) {
622 esv.AddEdt(dpi.PropertyCode, dpi.InputData);
623 enable = true;
624 }
625 }
626
627 if (!enable) {
628 return;
629 }
630 string call = m_WampClient.sendCall(esv.GetOption(), "jp.toppers.ecnl.procedure.set", "[]", esv.GetArguments(),
631 OnSetResponse);
632 if (call == null) {
633 Window.Alert("機器が接続されていません");
634 }
635 }
636
637 /// <summary>
638 /// 取得ボタンを押下
639 /// </summary>
640 /// <param name="ele"></param>
641 public void GetProperty(jQueryEvent eve)
642 {
643 string protocol = ((WampApiKadecotDevice)m_CurrentNode.Data).protocol;
644 if (protocol == "arduino") {
645 return;
646 }
647
648 WebApiGet esv = new WebApiGet();
649 //現在選択中のノードからEObjIDを取得
650 esv.deojid = (ENOD_ID)m_CurrentNode.EObjId;
651
652 //取得フラグ
653 bool enable = false;
654
655 foreach (var dpi in m_CurrentNode.Properties) {
656
657 if (dpi == null) {
658 continue;
659 }
660 dpi.IsWaitRes = false;
661
662 bool target = (dpi.Flag & EPC_FLAG.RULE_GET) != 0;
663
664 //読み込み禁止の場合
665 if (!target) {
666 dpi.ErrorText = "読み込み禁止です";
667 continue;
668 }
669 dpi.IsWaitRes = true;
670 esv.AddEpc(dpi.PropertyCode);
671 //読み込み可なのでtrue
672 enable = true;
673 }
674
675 if (!enable)
676 return;
677
678 string call = m_WampClient.sendCall(esv.GetOption(), "jp.toppers.ecnl.procedure.get", "[]", esv.GetArguments(),
679 OnResponse);
680 if (call == null) {
681 m_CurrentNode.GetDeviceBtn().ToggleClass("ui-icon-carat-r", "ui-icon-alert");
682 }
683 else {
684 m_CurrentNode.GetDeviceBtn().ToggleClass("ui-icon-alert", "ui-icon-carat-r");
685 }
686 }
687
688 /// <summary>
689 /// 設定と取得ボタンを押下
690 /// </summary>
691 /// <param name="ele"></param>
692 public void SetGetProperty(Element ele, jQueryEvent ev)
693 {
694 WebApiSet esv = new WebApiSet();
695
696 esv.deojid = (ENOD_ID)m_CurrentNode.EObjId;
697 bool enable = false;
698
699 foreach (var dpi in m_CurrentNode.Properties) {
700 if (dpi.InputData == null) {
701 continue;
702 }
703 else if (dpi.IsWaitRes) {
704 esv.AddEdt(dpi.PropertyCode, dpi.InputData);
705 enable = true;
706 }
707 }
708 if (!enable) {
709 return;
710 }
711 string call = m_WampClient.sendCall(esv.GetOption(), "jp.toppers.ecnl.procedure.setget", "[]", esv.GetArguments(),
712 OnResponse);
713 if (call == null) {
714 Window.Alert("機器が接続されていません");
715 }
716 }
717
718 /// <summary>
719 /// プロパティの値が変わった時
720 /// </summary>
721 /// <param name="ele"></param>
722 /// <param name="ev"></param>
723 public void PropertyChange(Element ele, jQueryEvent ev)
724 {
725 bool flag = m_CurrentNode.IsWait();
726 SetPropertyBtn.Disable(!flag);
727 SetGetPropertyBtn.Disable(!flag);
728 }
729
730 /// <summary>
731 /// Kadecotボタンをクリックした時に実行します
732 /// </summary>
733 /// <param name="ele"></param>
734 /// <param name="ev"></param>
735 public void KadecotClick(Element ele, jQueryEvent ev)
736 {
737 Window.Open("http://app.kadecot.net/index.html?kip=" + Window.Location.Hostname, "Kadecot");
738 }
739
740 DeviceController.DevicePropertyInfo dpi;
741
742 /// <summary>
743 /// 書き込み
744 /// </summary>
745 /// <param name="dpi"></param>
746 /// <param name="data"></param>
747 public void KadecotSet(DeviceController.DevicePropertyInfo dpi, byte[] data)
748 {
749 string propName;
750 if (dpi.PropertyCode == 0x80) {
751 propName = "OperationStatus";
752 }
753 else {
754 propName = "0x" + dpi.PropertyCode.ToString(16);
755 }
756
757 var di = m_CurrentNode;
758 if (di == null)
759 return;
760
761 this.dpi = dpi;
762 WampApiKadecotSet msg = new WampApiKadecotSet(di.EObjId, propName, data);
763
764 m_WampClient.sendCall(msg.GetOption(), "com.sonycsl.kadecot.echonetlite.procedure.set", "[]", msg.GetArguments(), KadecotSet);
765 }
766
767 /// <summary>
768 /// 書き込み
769 /// </summary>
770 /// <param name="args"></param>
771 private void KadecotSet(object args)
772 {
773 var di = m_CurrentNode;
774 dynamic doc = ((dynamic[])args)[4];
775
776 var res = new WampApiKadecotRes(doc);
777
778 if (m_DeviceController != null) {
779 m_DeviceController.RecvResponse(di, /*ESV_SET_RES*/0x71, this.dpi.PropertyCode, res.propertyValue);
780 }
781 }
782
783 public void KadecotGet(DeviceController.DevicePropertyInfo dpi)
784 {
785 string propName;
786 if (dpi.PropertyCode == 0x80) {
787 propName = "OperationStatus";
788 }
789 else {
790 propName = "0x" + dpi.PropertyCode.ToString(16);
791 }
792
793 var di = m_CurrentNode;
794 if (di == null)
795 return;
796
797 WampApiKadecotGet msg = new WampApiKadecotGet(di.EObjId, propName);
798 this.dpi = dpi;
799 m_WampClient.sendCall(msg.GetOption(), "com.sonycsl.kadecot.echonetlite.procedure.get", "[]", msg.GetArguments(), KadecotGet);
800 }
801
802 public void KadecotGet(object args)
803 {
804 var di = m_CurrentNode;
805 dynamic doc = ((dynamic[])args)[4];
806
807 var res = new WampApiKadecotRes(doc);
808
809 if (m_DeviceController != null) {
810 m_DeviceController.RecvResponse(di, /*ESV_GET_RES*/0x72, dpi.PropertyCode, res.propertyValue);
811 }
812 }
813
814 /// <summary>
815 /// 通信エラー発生時処理
816 /// </summary>
817 /// <param name="request"></param>
818 /// <param name="textStatus"></param>
819 /// <param name="error"></param>
820 private static void AjaxError(jQueryXmlHttpRequest request, string textStatus, dynamic error, string url)
821 {
822 var sep = new Regex("(\r\n|\r|\n)");
823 var lines = new List<string>();
824
825 lines.Add(textStatus);
826 if (error is string) {
827 lines.Add((string)error);
828 }
829 else {
830 lines.Add(error.message);
831
832 string stack = error.stack;
833 lines.AddRange(stack.Split(sep));
834 }
835
836 var html = jQuery.FromHtml("<p>");
837 foreach (var line in lines) {
838 if (sep.Exec(line) != null)
839 continue;
840 html.Append(Document.CreateTextNode(line).WholeText);
841 html.Append(jQuery.FromHtml("<br/>"));
842 }
843 html.Append(url + "の読み込みに失敗しました");
844 jQuery.Select("#popup_dialog_caption").Text("通信エラー");
845 jQuery.Select("#popup_dialog_title").Text("通信エラーが発生しました");
846 jQuery.Select("#popup_dialog_text").Html(html);
847 jQuery.Select("#popup_dialog").Popup("open", new { transition = "slidedown" });
848 }
849
850 /// <summary>
851 /// 設定・取得ボタンの有効・無効設定
852 /// </summary>
853 private void CurrentNodeChange(Element elem, jQueryEvent ev)
854 {
855 ButtonDisabled(m_CurrentNode);
856
857 if (m_CurrentNode == null) {
858 return;
859 }
860 PropertyCreate(m_CurrentNode);
861 GetProperty(ev);
862 return;
863 }
864
865 /// <summary>
866 /// 設定・取得ボタンを設定します
867 /// </summary>
868 /// <param name="di"></param>
869 private void ButtonDisabled(DeviceController.DeviceInfo di)
870 {
871 if (di == null) {
872 SetGetPropertyBtn.Disable(true);
873 GetPropertyBtn.Disable(true);
874 SetPropertyBtn.Disable(true);
875 return;
876 }
877
878 var ctrls = PropertyList;
879
880 SetGetPropertyBtn.Disable(ctrls == null);
881 GetPropertyBtn.Disable(ctrls == null);
882 SetPropertyBtn.Disable(ctrls == null);
883 }
884
885 /// <summary>
886 /// 入力画面を作成
887 /// </summary>
888 /// <param name="di"></param>
889 private void PropertyCreate(DeviceController.DeviceInfo di)
890 {
891 if (di == null) {
892 return;
893 }
894 jQuery.Document.Trigger(UIEventNames.PropertyWriteStart);
895 di.SetUIDevice(this);
896
897 PropertyList.Html("");
898 PropertyList.Append(di.GetPropertys());
899 PropertyList.ListView().ListView("refresh");
900 PropertyList.ListView().Trigger("create");
901
902 jQuery.Document.Trigger(UIEventNames.PropertyWriteEnd);
903 }
904
905 /// <summary>
906 /// 初期値設定ボタン
907 /// </summary>
908 /// <param name="elem"></param>
909 /// <param name="e"></param>
910 private void SetInitParams(Element elem, jQueryEvent e)
911 {
912 var macaddrfrm = new Regex("([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2})");
913
914 var m = macaddrfrm.Exec(MacAddrTxt.GetValue());
915 if (m == null)
916 return;
917
918 var ma1 = Byte.Parse(m[1], 16);
919 var ma2 = Byte.Parse(m[2], 16);
920 var ma3 = Byte.Parse(m[3], 16);
921 var ma4 = Byte.Parse(m[4], 16);
922 var ma5 = Byte.Parse(m[5], 16);
923 var ma6 = Byte.Parse(m[6], 16);
924
925 m_WampClient.sendCall("{}", "jp.toppers.ecnl.procedure.setInitParams", "[]",
926 "{\"macAddr\":[" + ma1 + "," + ma2 + "," + ma3 + "," + ma4 + "," + ma5 + "," + ma6 + "]}", SetInitParamsRes);
927 }
928
929 public void SetInitParamsRes(object args)
930 {
931 int cmd = (int)((dynamic[])args)[0];
932 if (cmd != (int)WAMP_MSG_TYPE.RESULT) {
933 jQuery.Select("#popup_dialog_caption").Text("エラー");
934 jQuery.Select("#popup_dialog_title").Text("エラーが発生しました");
935 jQuery.Select("#popup_dialog_text").Text("初期データの書き込みに失敗しました。");
936 jQuery.Select("#popup_dialog").Popup("open", new { transition = "slidedown" });
937 return;
938 }
939
940 jQuery.Select("#popup_dialog_caption").Text("初期データ");
941 jQuery.Select("#popup_dialog_title").Text("初期データを書き込みました");
942 jQuery.Select("#popup_dialog_text").Text("初期データの書き込みに成功しました。");
943 jQuery.Select("#popup_dialog").Popup("open", new { transition = "slidedown" });
944 }
945
946 /// <summary>
947 /// 初期値設定ボタン
948 /// </summary>
949 /// <param name="elem"></param>
950 /// <param name="e"></param>
951 private void GetInitParams(Element elem, jQueryEvent e)
952 {
953 m_WampClient.sendCall("{}", "jp.toppers.ecnl.procedure.getInitParams", "[]", "{}", GetInitParamsRes);
954 }
955
956 public void GetInitParamsRes(object args)
957 {
958 int cmd = (int)((dynamic[])args)[0];
959 if (cmd != (int)WAMP_MSG_TYPE.RESULT) {
960 jQuery.Select("#popup_dialog_caption").Text("エラー");
961 jQuery.Select("#popup_dialog_title").Text("エラーが発生しました");
962 jQuery.Select("#popup_dialog_text").Text("初期データの読み込みに失敗しました。");
963 jQuery.Select("#popup_dialog").Popup("open", new { transition = "slidedown" });
964 return;
965 }
966
967 var macaddr = (byte[])(((dynamic[])args)[4].macAddr);
968 MacAddrTxt.Value(String.Format("{0:X02}:{1:X02}:{2:X02}:{3:X02}:{4:X02}:{5:X02}",
969 macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]));
970 }
971
972 /// <summary>設定ボタン</summary>
973 public jQueryObject SetPropertyBtn { get { return jQuery.Select("#bt_set_property", page); } }
974
975 /// <summary>取得ボタン</summary>
976 public jQueryObject GetPropertyBtn { get { return jQuery.Select("#bt_get_property", page); } }
977
978 /// <summary>設定と取得ボタン</summary>
979 public jQueryObject SetGetPropertyBtn { get { return jQuery.Select("#bt_set_get_property", page); } }
980
981 /// <summary>Kadecotボタン</summary>
982 public jQueryObject KadecotBtn { get { return jQuery.Select("#bt_kadecot", page); } }
983
984 /// <summary>接続スイッチ</summary>
985 public jQueryObject ConnectionSwt { get { return jQuery.Select("#fs_connection", page); } }
986
987 /// <summary>プロパティリスト</summary>
988 public jQueryObject PropertyList { get { return jQuery.Select("#lv_property_list", page); } }
989
990 /// <summary>機器検索ボタン</summary>
991 public jQueryObject SearchBtn { get { return jQuery.Select("#bt_search", page); } }
992
993 /// <summary>ノードリスト</summary>
994 public jQueryObject NodeList { get { return jQuery.Select("#node_list", page); } }
995
996 /// <summary>groupBox</summary>
997 public jQueryObject PropertyGroupBox { get { return jQuery.Select("#lv_property_list", page).Find("li"); } }
998
999 /// <summary>初期値設定ボタン</summary>
1000 public jQueryObject SetInitParamsBtn { get { return jQuery.Select("#bt_set_init_params", page); } }
1001
1002 /// <summary>初期値取得ボタン</summary>
1003 public jQueryObject GetInitParamsBtn { get { return jQuery.Select("#bt_get_init_params", page); } }
1004
1005 /// <summary>MACアドレス入力</summary>
1006 public jQueryObject MacAddrTxt { get { return jQuery.Select("#txt_mac_addr", page); } }
1007
1008 public void pinMode_Change(UIFieldSet fieldset, int pin)
1009 {
1010 string value = fieldset.CheckdValue();
1011 JsDictionary dic = new JsDictionary("pin", pin, "mode", value);
1012 m_WampClient.sendCall("{\"deviceId\":" + 1 + "}", "com.sonycsl.kadecot.arduino.pinMode", "[]", Json.Stringify(dic), pinMode);
1013 }
1014
1015 public void digital_Change(UIButton button, UIFlipSwitch flipswitch, int pin)
1016 {
1017 WampApiKadecotSet msg = new WampApiKadecotSet(1, "2", new byte[2]);
1018 JsDictionary dic = new JsDictionary("pin", pin, "value", flipswitch.Value);
1019 m_WampClient.sendCall("{\"deviceId\":" + 1 + "}", "com.sonycsl.kadecot.arduino.digitalWrite", "[]", Json.Stringify(dic), digitalWrite);
1020 }
1021
1022 public void analogWrite_Change(UIRangeInput range, int pin)
1023 {
1024 WampApiKadecotSet msg = new WampApiKadecotSet(1, "2", new byte[2]);
1025 JsDictionary dic = new JsDictionary("pin", pin, "value", range.Value);
1026 m_WampClient.sendCall("{\"deviceId\":" + 1 + "}", "com.sonycsl.kadecot.arduino.analogWrite", "[]", Json.Stringify(dic), pinMode);
1027 }
1028
1029 public void analogRead(UIRangeInput range, int pin)
1030 {
1031 JsDictionary dic = new JsDictionary("pin", pin);
1032 m_WampClient.sendCall("{\"deviceId\":" + 1 + "}", "com.sonycsl.kadecot.arduino.analogRead", "[]", Json.Stringify(dic), (args) => { digitalRead(args, range); });
1033 }
1034
1035 public void pinMode(object args)
1036 {
1037 int switchData = (int)((dynamic[])args)[0];
1038 if (switchData != (int)WAMP_MSG_TYPE.RESULT) {
1039 return;
1040 }
1041 dynamic doc = ((dynamic[])args)[4];
1042 if (m_DeviceController != null) {
1043 if (PropertyList == null)
1044 return;
1045 }
1046 }
1047
1048 public void digitalWrite(object args)
1049 {
1050 int switchData = (int)((dynamic[])args)[0];
1051 if (switchData != (int)WAMP_MSG_TYPE.RESULT) {
1052 return;
1053 }
1054 dynamic doc = ((dynamic[])args)[4];
1055 if (m_DeviceController != null) {
1056 if (PropertyList == null)
1057 return;
1058 }
1059 }
1060
1061 public void DigitalRead(UIButton button, UIFlipSwitch flip, int i)
1062 {
1063 JsDictionary dic = new JsDictionary("pin", i);
1064 string str = m_WampClient.sendCall("{\"deviceId\":" + 1 + "}", "com.sonycsl.kadecot.arduino.digitalRead", "[]", Json.Stringify(dic), (arg) => { digitalRead(arg, flip); });
1065 if (str == null) {
1066 button.ToggleClass("ui-icon-refresh", "ui-icon-alert");
1067 }
1068 else {
1069 button.ToggleClass("ui-icon-alert", "ui-icon-refresh");
1070 }
1071 }
1072
1073 public void digitalRead(object args, UIObject uiobject)
1074 {
1075 int switchData = (int)((dynamic[])args)[0];
1076 if (switchData != (int)WAMP_MSG_TYPE.RESULT) {
1077 return;
1078 }
1079 dynamic doc = ((dynamic[])args)[4];
1080 if (m_DeviceController != null) {
1081
1082 WebApiGrsaguraMessage msg = new WebApiGrsaguraMessage(doc);
1083 if (uiobject.GetType() == typeof(UIFlipSwitch)) {
1084 UIFlipSwitch flip = (UIFlipSwitch)uiobject;
1085 flip.Value = msg.value;
1086 }
1087 else if (uiobject.GetType() == typeof(UIRangeInput)) {
1088 UIRangeInput range = (UIRangeInput)uiobject;
1089 range.Value = int.Parse(msg.value);
1090 range.Object.Slider("refresh");
1091 }
1092 }
1093 }
1094}
1095
1096namespace ctrlui
1097{
1098 public class Information
1099 {
1100 private jQueryObject info;
1101
1102 public Information()
1103 {
1104 }
1105
1106 public void Update(Element ele, string id)
1107 {
1108 var page = CtrlUI.GetPage(ele);
1109
1110 this.info = jQuery.Select("#" + id, page);
1111 if (this.info == null)
1112 return;
1113 jQuery.Ajax("./" + id + ".json").Success(this.Success).Error(this.Error);
1114 }
1115
1116 private void Success(object data, string textStatus, jQueryXmlHttpRequest request)
1117 {
1118 var items = (dynamic[])((data.GetType() == typeof(string)) ? jQuery.ParseJson((string)data) : data);
1119
1120 var listview = new UIListview("data-inset", true, "data-theme", "b").Object;
1121 listview.Append(new UIListDivider("ソフトウェア情報").Object);
1122
1123 foreach (var item in items) {
1124 string title = item.title;
1125 string version = item.version;
1126 string link = item.link;
1127 string note = item.note;
1128
1129 UIAnchor a;
1130 if (String.IsNullOrEmpty(link)) {
1131 a = new UIAnchor(new UIH(2, title));
1132 a.Href = "#";
1133 }
1134 else {
1135 a = new UIAnchor(new UIH(2, title));
1136 a.Href = link;
1137 a.Target = "_blank";
1138 }
1139 a.Append(new UIP("Version " + version));
1140 if (!String.IsNullOrEmpty(note))
1141 a.Append(new UIP(note));
1142 listview.Append(new UIListviewItem(a).Object);
1143 }
1144 UIAnchor anchor = new UIAnchor();
1145 anchor.Target = "_blank";
1146 anchor.Href = "http://www.core-s.co.jp";
1147 anchor.Append(new UIImg("src", "imgs/core-s.svg").Object).Append("コアーズ株式会社");
1148
1149 var listitem = new UIListDivider(anchor).Object;
1150
1151 listview.Append(listitem);
1152 this.info.Html("");
1153 this.info.Append(listview);
1154
1155 jQuery.Select("ul", this.info).ListView().ListView("refresh");
1156 this.info.Popup("reposition", new { positionTo = "origin" });
1157 }
1158
1159 private void Error(jQueryXmlHttpRequest request, string textStatus, Exception error)
1160 {
1161 jQueryObject listview = new UIListview("data-inset", "true", "data-theme", "b").Object;
1162 listview.Append(new UIListDivider("ソフトウェア情報").Object);
1163 listview.Append(new UIListviewItem(new UIP("通信エラー")).Object);
1164
1165 this.info.Append(listview);
1166 jQuery.Select("ul", this.info).ListView().ListView("refresh");
1167 this.info.Popup("reposition", new { positionTo = "origin" });
1168 }
1169 }
1170}
Note: See TracBrowser for help on using the repository browser.