util.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. const formatTime = date => {
  2. const year = date.getFullYear()
  3. const month = date.getMonth() + 1
  4. const day = date.getDate()
  5. const hour = date.getHours()
  6. const minute = date.getMinutes()
  7. const second = date.getSeconds()
  8. return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
  9. }
  10. const formatNumber = n => {
  11. n = n.toString()
  12. return n[1] ? n : `0${n}`
  13. }
  14. const FRAME_CTRL_POSITION_ENCRYPTED = 0;
  15. const FRAME_CTRL_POSITION_CHECKSUM = 1;
  16. const FRAME_CTRL_POSITION_DATA_DIRECTION = 2;
  17. const FRAME_CTRL_POSITION_REQUIRE_ACK = 3;
  18. const FRAME_CTRL_POSITION_FRAG = 4;
  19. const DIRECTION_OUTPUT = 0;
  20. const DIRECTION_INPUT = 1;
  21. const AES_BASE_IV = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  22. const NEG_SET_SEC_TOTAL_LEN = 0x00;
  23. const NEG_SET_SEC_ALL_DATA = 0x01;
  24. const PACKAGE_VALUE = 0x01;
  25. const SUBTYPE_NEG = 0x00;
  26. const SUBTYPE_END = 0x03;
  27. const SUBTYPE_WIFI_NEG = 0x09;
  28. const SUBTYPE_SET_SSID = 0x2;
  29. const SUBTYPE_SET_PWD = 0x3;
  30. const SUBTYPE_WIFI_LIST_NEG = 11;
  31. const SUBTYPE_NEGOTIATION_NEG = 0;
  32. const SUBTYPE_CUSTOM_DATA = 0x13;
  33. const PACKAGE_MSG_HEADER = 0xCD;
  34. const PACKAGE_MSG_TYPE = 0x1F;
  35. var DH_P = "cf5cf5c38419a724957ff5dd323b9c45c3cdd261eb740f69aa94b8bb1a5c96409153bd76b24222d03274e4725a5406092e9e82e9135c643cae98132b0d95f7d65347c68afc1e677da90e51bbab5f5cf429c291b4ba39c6b2dc5e8c7231e46aa7728e87664532cdf547be20c9a3fa8342be6e34371a27c06f7dc0edddd2f86373";
  36. var DH_G = "02";
  37. const descSucList = ["蓝牙连接...", "蓝牙连接成功", "成功获取设备信息", "获取属性信息成功", "发送配置信息...", "配置信息发送成功", "连接成功"];
  38. const descFailList = ["蓝牙连接失败", "获取设备信息失败", "获取属性信息失败", "发送配置信息失败", "分配网络失败"];
  39. const successList = { "0": "NULL", "1": "STA", "2": "SoftAP", "3": "SoftAP & STA" };
  40. const failList = { "0": "sequence error", "1": "checksum error", "2": "decrypt error", "3": "encrypt error", "4": "init security error", "5": "dh malloc error", "6": "dh param error", "7": "read param error", "8": "make public error" };
  41. var CRC_TB = [
  42. 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  43. 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  44. 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  45. 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  46. 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  47. 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  48. 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  49. 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  50. 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  51. 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  52. 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  53. 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  54. 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  55. 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  56. 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  57. 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  58. ];
  59. const showToast = title => {
  60. wx.showToast({
  61. title: title,
  62. icon: 'none',
  63. duration: 2000
  64. })
  65. }
  66. //转16进制
  67. const ab2hex = buffer => {
  68. var hexArr = Array.prototype.map.call(
  69. new Uint8Array(buffer),
  70. function (bit) {
  71. return ('00' + bit.toString(16)).slice(-2)
  72. }
  73. )
  74. return hexArr;
  75. }
  76. //16进制转字符串
  77. const hexCharCodeToStr = hexCharCodeStr => {
  78. var trimedStr = hexCharCodeStr.trim();
  79. var rawStr =
  80. trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
  81. var len = rawStr.length;
  82. if (len % 2 !== 0) {
  83. alert("非法格式ASCII码!");
  84. return "";
  85. }
  86. var curCharCode;
  87. var resultStr = [];
  88. for (var i = 0; i < len; i = i + 2) {
  89. curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
  90. resultStr.push(String.fromCharCode(curCharCode));
  91. }
  92. return resultStr.join("");
  93. }
  94. //过滤名称
  95. const filterDevice = (devices, name) => {
  96. var list = [];
  97. for (var i = 0; i < devices.length; i++) {
  98. var device = devices[i];
  99. if (device[name] != '') {
  100. //console.log(device[name])
  101. if (device[name].indexOf('LZ-OTA') !== -1) {
  102. device['beOnline'] = '';
  103. list.push(device);
  104. }
  105. }
  106. }
  107. return list;
  108. // var arr = sortArrObj(list,[['RSSI','asc']]);
  109. // return arr.length > 3?arr.slice(0,3):arr;
  110. }
  111. //获去type
  112. const getType = (pkgType, subType) => {
  113. return (subType << 2) | pkgType;
  114. }
  115. //unit8Arry转数组
  116. const uint8ArrayToArray = uint8Array => {
  117. var array = [];
  118. for (var i = 0; i < uint8Array.byteLength; i++) {
  119. array[i] = uint8Array[i];
  120. }
  121. return array;
  122. }
  123. //16进制转二进制数组
  124. const hexToBinArray = str => {
  125. var dec = parseInt(str, 16),
  126. bin = dec.toString(2),
  127. len = bin.length;
  128. if (len < 8) {
  129. var diff = 8 - len,
  130. zeros = "";
  131. for (var i = 0; i < diff; i++) {
  132. zeros += "0";
  133. }
  134. bin = zeros + bin;
  135. }
  136. return bin.split("");
  137. }
  138. //16进制转数组
  139. const hexByArray = str => {
  140. var arr = [];
  141. if (str.length % 2 != 0) {
  142. str = "0" + str;
  143. }
  144. for (var i = 0; i < str.length; i += 2) {
  145. arr.push(str.substring(i, i + 2))
  146. }
  147. return arr;
  148. }
  149. //16进制转整形数组
  150. const hexByInt = str => {
  151. var arr = [];
  152. if (str.length % 2 != 0) {
  153. str = "0" + str;
  154. }
  155. for (var i = 0; i < str.length; i += 2) {
  156. arr.push(parseInt(str.substring(i, i + 2), 16))
  157. }
  158. return arr;
  159. }
  160. //排序
  161. const sortBy = (attr, rev) => {
  162. //第二个参数没有传递 默认升序排列
  163. if (rev == undefined) {
  164. rev = 1;
  165. } else {
  166. rev = (rev) ? 1 : -1;
  167. }
  168. return function (a, b) {
  169. a = a[attr];
  170. b = b[attr];
  171. if (a < b) {
  172. return rev * -1;
  173. } else if (a > b) {
  174. return rev * 1;
  175. }
  176. return 0;
  177. }
  178. }
  179. /**
  180. * 对数组对象的指定属性进行排序
  181. * @param {Array} arr 数组对象
  182. * @param {Array} rules 排序规则,每个元素都是形如 ['key', 'asc'] 或者 ['key', 'desc'] 的数组
  183. */
  184. function sortArrObj(arr, rules) {
  185. return arr.sort((a, b) => {
  186. for (let i = 0; i < rules.length; i++) {
  187. const [key, direction] = rules[i];
  188. const order = direction === 'desc' ? -1 : 1;
  189. if (a[key] < b[key]) {
  190. return -1 * order;
  191. }
  192. if (a[key] > b[key]) {
  193. return 1 * order;
  194. }
  195. }
  196. return 0;
  197. });
  198. }
  199. //判断非空
  200. const _isEmpty = str => {
  201. if (str === "" || str === null || str === undefined || str === "null" || str === "undefined") {
  202. return true;
  203. } else {
  204. return false;
  205. }
  206. }
  207. //组装数据格式
  208. const writeData = (data) => {
  209. var value = [];
  210. value.push(0xcd);
  211. value.push(0x1f);
  212. value.push(0x00);
  213. value.push(data.length + 4);
  214. value = value.concat(data);
  215. value.push(0xcd);
  216. value.push(0x0e);
  217. value.push(0x00);
  218. value.push(0x04);
  219. // value.push(0xff);
  220. // value.push(0xff);
  221. // value.push(0xff);
  222. // value.push(0xff);
  223. return value;
  224. }
  225. const writeSetting = (data) => {
  226. var value = [];
  227. value.push(0xcd);
  228. value.push(0x23);
  229. value.push(0x00);
  230. value.push(data.length + 4);
  231. value = value.concat(data);
  232. value.push(0xff);
  233. value.push(0xff);
  234. value.push(0xff);
  235. value.push(0xff);
  236. return value;
  237. }
  238. //是否分包
  239. const isSubcontractor = (data, checksum, sequence) => {
  240. var len = 0, lenData = [], laveData = [], flag = false;
  241. var total = data.length;
  242. if (total > 20) {
  243. if (checksum) {
  244. lenData = data.slice(0, 18);
  245. laveData = data.slice(18);
  246. } else {
  247. lenData = data.slice(0, 14);
  248. laveData = data.slice(14);
  249. }
  250. len = lenData.length;
  251. flag = true;
  252. } else {
  253. lenData = data;
  254. len = lenData.length;
  255. }
  256. if (checksum) {
  257. //lenData = assemblyChecksum(lenData, len, sequence);
  258. }
  259. return { "len": len, "lenData": lenData, "laveData": laveData, "flag": flag }
  260. }
  261. const assemblyChecksum = (list, len, sequence, encrypt) => {
  262. var checkData = [];
  263. checkData.push(sequence);
  264. checkData.push(len);
  265. checkData = checkData.concat(list);
  266. var crc = caluCRC(0, checkData);
  267. var checksumByte1 = crc & 0xff;
  268. var checksumByte2 = (crc >> 8) & 0xff;
  269. list.push(checksumByte1);
  270. list.push(checksumByte2);
  271. return list;
  272. }
  273. //加密发送的数据
  274. const encrypt = (aesjs, md5Key, sequence, data, checksum) => {
  275. var iv = generateAESIV(sequence), sumArr = [], list = [];
  276. if (checksum) {
  277. var len = data.length - 2;
  278. list = data.slice(0, len);
  279. sumArr = data.slice(len);
  280. } else {
  281. list = data;
  282. }
  283. var encryptData = uint8ArrayToArray(blueAesEncrypt(aesjs, md5Key, iv, new Uint8Array(list)));
  284. return encryptData.concat(sumArr);
  285. }
  286. // aes加密
  287. const blueAesEncrypt = (aesjs, mdKey, iv, bytes) => {
  288. var aesOfb = new aesjs.ModeOfOperation.ofb(mdKey, iv);
  289. var encryptedBytes = aesOfb.encrypt(bytes);
  290. return encryptedBytes;
  291. }
  292. //获取Frame Control
  293. const getFrameCTRLValue = (encrypted, checksum, direction, requireAck, frag) => {
  294. var frame = 0;
  295. if (encrypted) {
  296. frame = frame | (1 << FRAME_CTRL_POSITION_ENCRYPTED);
  297. }
  298. if (checksum) {
  299. frame = frame | (1 << FRAME_CTRL_POSITION_CHECKSUM);
  300. }
  301. if (direction == DIRECTION_INPUT) {
  302. frame = frame | (1 << FRAME_CTRL_POSITION_DATA_DIRECTION);
  303. }
  304. if (requireAck) {
  305. frame = frame | (1 << FRAME_CTRL_POSITION_REQUIRE_ACK);
  306. }
  307. if (frag) {
  308. frame = frame | (1 << FRAME_CTRL_POSITION_FRAG);
  309. }
  310. return frame;
  311. }
  312. //获取aes iv
  313. const generateAESIV = sequence => {
  314. var result = [];
  315. for (var i = 0; i < 16; i++) {
  316. if (i == 0) {
  317. result[0] = sequence;
  318. } else {
  319. result[i] = AES_BASE_IV[i];
  320. }
  321. }
  322. return result;
  323. }
  324. //计算CRC值
  325. const caluCRC = (crc, pByte) => {
  326. crc = (~crc) & 0xffff;
  327. for (var i in pByte) {
  328. crc = CRC_TB[((crc & 0xffff) >> 8) ^ (pByte[i] & 0xff)] ^ ((crc & 0xffff) << 8);
  329. }
  330. return (~crc) & 0xffff;
  331. }
  332. const hsvToRgb = (h, s, v) => {
  333. var r, g, b;
  334. var i = Math.floor(h * 6);
  335. var f = h * 6 - i;
  336. var p = v * (1 - s);
  337. var q = v * (1 - f * s);
  338. var t = v * (1 - (1 - f) * s);
  339. switch (i % 6) {
  340. case 0: r = v, g = t, b = p; break;
  341. case 1: r = q, g = v, b = p; break;
  342. case 2: r = p, g = v, b = t; break;
  343. case 3: r = p, g = q, b = v; break;
  344. case 4: r = t, g = p, b = v; break;
  345. case 5: r = v, g = p, b = q; break;
  346. }
  347. return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
  348. }
  349. const rgbToHsv = (r, g, b) => {
  350. r = r / 255, g = g / 255, b = b / 255;
  351. var max = Math.max(r, g, b), min = Math.min(r, g, b);
  352. var h, s, v = max;
  353. var d = max - min;
  354. s = max == 0 ? 0 : d / max;
  355. if (max == min) {
  356. h = 0; // achromatic
  357. } else {
  358. switch (max) {
  359. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  360. case g: h = (b - r) / d + 2; break;
  361. case b: h = (r - g) / d + 4; break;
  362. }
  363. h /= 6;
  364. }
  365. return Math.round(h * 360);
  366. }
  367. const createCanvas = (self) => {
  368. var context = wx.createCanvasContext('firstCanvas', self);
  369. var width = Math.floor(self.data.width * 0.7),
  370. height = width,
  371. cx = width / 2,
  372. cy = height / 2,
  373. radius = width / 2.3,
  374. imageData,
  375. pixels,
  376. hue, sat, value,
  377. i = 0, x, y, rx, ry, d,
  378. f, g, p, u, v, w, rgb;
  379. wx.canvasGetImageData({
  380. canvasId: 'firstCanvas',
  381. x: 0,
  382. y: 0,
  383. width: width,
  384. height: height,
  385. success(res) {
  386. var pixels = res.data;
  387. for (y = 0; y < height; y++) {
  388. for (x = 0; x < width; x++, i = i + 4) {
  389. rx = x - cx;
  390. ry = y - cy;
  391. d = rx * rx + ry * ry;
  392. if (d < radius * radius) {
  393. hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI);
  394. sat = Math.sqrt(d) / radius;
  395. g = Math.floor(hue);
  396. f = hue - g;
  397. u = 255 * (1 - sat);
  398. v = 255 * (1 - sat * f);
  399. w = 255 * (1 - sat * (1 - f));
  400. pixels[i] = [255, v, u, u, w, 255, 255][g];
  401. pixels[i + 1] = [w, 255, 255, v, u, u, w][g];
  402. pixels[i + 2] = [u, u, w, 255, 255, v, u][g];
  403. pixels[i + 3] = 255;
  404. }
  405. }
  406. }
  407. wx.canvasPutImageData({
  408. canvasId: 'firstCanvas',
  409. x: 0,
  410. y: 0,
  411. width: width,
  412. height: height,
  413. data: pixels,
  414. success(res) {
  415. setTimeout(function () {
  416. context.beginPath();
  417. context.arc(cx, cy, radius * 0.6, 0, 2 * Math.PI);
  418. context.fillStyle = "#12151e";
  419. context.fill();
  420. context.stroke();
  421. context.draw(true);
  422. context.beginPath();
  423. context.arc(cx, cy, radius, 0, 2 * Math.PI);
  424. context.strokeStyle = "#12151e";
  425. context.lineWidth = 5;
  426. context.stroke();
  427. context.draw(true);
  428. })
  429. },
  430. fail(res) {
  431. }
  432. }, self)
  433. }
  434. })
  435. }
  436. const getColor = (self, event) => {
  437. //console.log(event);
  438. var x = event.touches[0].x,
  439. y = event.touches[0].y;
  440. wx.canvasGetImageData({
  441. canvasId: "firstCanvas",
  442. x: x,
  443. y: y,
  444. width: 1,
  445. height: 1,
  446. success(res) {
  447. var r = res.data[0],
  448. g = res.data[1],
  449. b = res.data[2];
  450. //console.log(r, g, b);
  451. // 特殊值过滤
  452. if ((r == 0 && g == 0 && b == 0) || (r == 18 && g == 21 && b == 30)) {
  453. return false;
  454. } else {
  455. self.setData({
  456. color: "rgba(" + r + ", " + g + ", " + b + ", " + self.data.currentLuminanceText / 100 + ")",
  457. currentSaturationText: 100,
  458. currentSaturation: 100,
  459. currentHue: rgbToHsv(r, g, b)
  460. })
  461. self.setDeviceStatus();
  462. }
  463. }
  464. })
  465. }
  466. module.exports = {
  467. formatTime,
  468. showToast: showToast,
  469. ab2hex: ab2hex,
  470. hexCharCodeToStr: hexCharCodeToStr,
  471. filterDevice: filterDevice,
  472. getType: getType,
  473. hexToBinArray: hexToBinArray,
  474. hexByArray: hexByArray,
  475. hexByInt: hexByInt,
  476. sortBy: sortBy,
  477. sortArrObj: sortArrObj,
  478. writeData: writeData,
  479. writeSetting: writeSetting,
  480. isSubcontractor: isSubcontractor,
  481. getFrameCTRLValue: getFrameCTRLValue,
  482. uint8ArrayToArray: uint8ArrayToArray,
  483. generateAESIV: generateAESIV,
  484. caluCRC: caluCRC,
  485. encrypt: encrypt,
  486. DH_P: DH_P,
  487. DH_G: DH_G,
  488. DIRECTION_OUTPUT: DIRECTION_OUTPUT,
  489. DIRECTION_INPUT: DIRECTION_INPUT,
  490. NEG_SET_SEC_TOTAL_LEN: NEG_SET_SEC_TOTAL_LEN,
  491. NEG_SET_SEC_ALL_DATA: NEG_SET_SEC_ALL_DATA,
  492. PACKAGE_VALUE: PACKAGE_VALUE,
  493. SUBTYPE_NEG: SUBTYPE_NEG,
  494. PACKAGE_CONTROL_VALUE: PACKAGE_MSG_HEADER,
  495. SUBTYPE_WIFI_MODEl: PACKAGE_MSG_TYPE,
  496. SUBTYPE_WIFI_NEG: SUBTYPE_WIFI_NEG,
  497. SUBTYPE_WIFI_LIST_NEG: SUBTYPE_WIFI_LIST_NEG,
  498. SUBTYPE_NEGOTIATION_NEG: SUBTYPE_NEGOTIATION_NEG,
  499. SUBTYPE_SET_SSID: SUBTYPE_SET_SSID,
  500. SUBTYPE_SET_PWD: SUBTYPE_SET_PWD,
  501. SUBTYPE_END: SUBTYPE_END,
  502. SUBTYPE_CUSTOM_DATA: SUBTYPE_CUSTOM_DATA,
  503. hsvToRgb: hsvToRgb,
  504. rgbToHsv: rgbToHsv,
  505. createCanvas: createCanvas,
  506. getColor: getColor,
  507. descSucList: descSucList,
  508. descFailList: descFailList,
  509. successList: successList,
  510. _isEmpty: _isEmpty
  511. }