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