@meta2d/core 1.0.71 → 1.0.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/core.d.ts CHANGED
@@ -3,7 +3,7 @@ import { Canvas } from './canvas';
3
3
  import { Options, PenPlugin, PluginOptions } from './options';
4
4
  import { calcTextDrawRect, calcTextLines, calcTextRect, facePen, getWords, LockState, Pen, renderPenRaw, IValue, setElemPosition } from './pen';
5
5
  import { Point } from './point';
6
- import { EditAction, register, registerAnchors, registerCanvasDraw, Meta2dData, Meta2dStore, Network, HttpOptions } from './store';
6
+ import { EditAction, register, registerAnchors, registerCanvasDraw, Meta2dData, Meta2dStore, Network, HttpOptions, Sql } from './store';
7
7
  import { Padding } from './utils';
8
8
  import { Rect } from './rect';
9
9
  import { Event, TriggerCondition } from './event';
@@ -17,6 +17,7 @@ export declare class Meta2d {
17
17
  mqttClient: MqttClient;
18
18
  websockets: WebSocket[];
19
19
  mqttClients: MqttClient[];
20
+ eventSources: EventSource[];
20
21
  penPluginMap: Map<PenPlugin, {
21
22
  tag?: string;
22
23
  name?: string;
@@ -235,9 +236,17 @@ export declare class Meta2d {
235
236
  updateTimerList: any[];
236
237
  sqlTimerList: any[];
237
238
  connectNetwork(): void;
239
+ iotMqttClient: MqttClient;
240
+ iotTimer: any;
241
+ iotWebsocketClient: WebSocket;
242
+ connectIot(): Promise<void>;
243
+ connectSqls(): void;
244
+ connectSSE(net: Network): void;
245
+ closeSSE(): void;
238
246
  connectNetWebSocket(net: Network): void;
239
- getIotToken(devices: any): Promise<any>;
240
- doSqlCode(type: string, dbid: string, sql: string): Promise<void>;
247
+ getMqttUrl(): Promise<string>;
248
+ getIotToken(devices: any, type: number): Promise<any>;
249
+ doSqlCode(sql: Sql): Promise<void>;
241
250
  randomString(e: number): string;
242
251
  mockValue(data: any): any;
243
252
  dataMock(): void;
package/src/core.js CHANGED
@@ -13,7 +13,7 @@ import pkg from '../package.json';
13
13
  import { lockedError } from './utils/error';
14
14
  import { Scroll } from './scroll';
15
15
  import { getter } from './utils/object';
16
- import { getCookie, getMeta2dData, queryURLParams } from './utils/url';
16
+ import { getCookie, getMeta2dData, getToken, queryURLParams } from './utils/url';
17
17
  import { HotkeyType } from './data';
18
18
  import { Message, messageList } from './message';
19
19
  import { closeJetLinks, connectJetLinks, getSendData, sendJetLinksData } from './utils/jetLinks';
@@ -25,6 +25,7 @@ export class Meta2d {
25
25
  mqttClient;
26
26
  websockets;
27
27
  mqttClients;
28
+ eventSources;
28
29
  penPluginMap = new Map();
29
30
  socketFn;
30
31
  events = {};
@@ -134,6 +135,7 @@ export class Meta2d {
134
135
  this.canvas.scroll && this.canvas.scroll.hide();
135
136
  }
136
137
  }
138
+ this.canvas?.initGlobalStyle();
137
139
  }
138
140
  getOptions() {
139
141
  return this.store.options;
@@ -151,6 +153,11 @@ export class Meta2d {
151
153
  // 更新全局的主题css变量
152
154
  le5leTheme.updateCssRule(this.store.id, theme);
153
155
  this.canvas.initGlobalStyle();
156
+ for (let i = 0; i < this.store.data.pens.length; i++) {
157
+ const pen = this.store.data.pens[i];
158
+ // 调用pen的主题设置函数,如果单个pen有主题的自定义设置的话
159
+ pen.setTheme && pen.setTheme(pen, this.store.styles);
160
+ }
154
161
  this.render();
155
162
  }
156
163
  setDatabyOptions(options = {}) {
@@ -528,6 +535,7 @@ export class Meta2d {
528
535
  const data = await getMeta2dData(this.store, id);
529
536
  if (data) {
530
537
  this.open(data);
538
+ this.fitView(true, 10);
531
539
  }
532
540
  }
533
541
  doSendDataEvent(value, topics) {
@@ -919,6 +927,8 @@ export class Meta2d {
919
927
  initBinds() {
920
928
  this.jetLinksList = [];
921
929
  this.store.bind = {};
930
+ const devices = [];
931
+ const properties = [];
922
932
  this.store.data.pens.forEach((pen) => {
923
933
  pen.realTimes?.forEach((realTime) => {
924
934
  if (realTime.bind && realTime.bind.id) {
@@ -981,9 +991,55 @@ export class Meta2d {
981
991
  });
982
992
  }
983
993
  }
994
+ if (realTime.bind.class === 'iot') {
995
+ let bind = realTime.bind.id.split('#');
996
+ let idx = devices.findIndex((item) => item.deviceId === bind[0]);
997
+ if (idx > -1) {
998
+ if (!devices[idx].properties.includes(bind[1])) {
999
+ devices[idx].properties.push(bind[1]);
1000
+ }
1001
+ }
1002
+ else {
1003
+ devices.push({
1004
+ deviceId: bind[0],
1005
+ properties: [bind[1]],
1006
+ token: realTime.bind.token
1007
+ });
1008
+ }
1009
+ let index = properties.findIndex((item) => item.key === realTime.bind.id);
1010
+ if (index === -1) {
1011
+ properties.push({
1012
+ key: realTime.bind.id,
1013
+ label: realTime.bind.label,
1014
+ });
1015
+ }
1016
+ }
1017
+ else if (realTime.bind.class === 'sql') {
1018
+ let bind = realTime.bind.id.split('#');
1019
+ const sql = this.store.data.sqls.find((item) => item.bindId === bind[0]);
1020
+ if (sql) {
1021
+ if (!sql.keys) {
1022
+ sql.keys = [];
1023
+ }
1024
+ bind.shift();
1025
+ const key = bind.join('#');
1026
+ if (!sql.keys.includes(key)) {
1027
+ sql.keys.push(key);
1028
+ }
1029
+ }
1030
+ }
984
1031
  }
985
1032
  });
986
1033
  });
1034
+ if (devices.length) {
1035
+ if (!this.store.data.iot) {
1036
+ this.store.data.iot = {};
1037
+ }
1038
+ this.store.data.iot.devices = devices;
1039
+ }
1040
+ if (properties.length) {
1041
+ this.store.data.iot.list = properties;
1042
+ }
987
1043
  }
988
1044
  connectSocket() {
989
1045
  this.connectWebsocket();
@@ -1931,8 +1987,10 @@ export class Meta2d {
1931
1987
  let mqttIndex = 0;
1932
1988
  this.mqttClients = [];
1933
1989
  let websocketIndex = 0;
1990
+ let sseIndex = 0;
1934
1991
  let sqlIndex = 0;
1935
1992
  this.websockets = [];
1993
+ this.eventSources = [];
1936
1994
  networks.forEach(async (net) => {
1937
1995
  // if (net.type === 'subscribe') {
1938
1996
  if (net.protocol === 'mqtt') {
@@ -2001,54 +2059,101 @@ export class Meta2d {
2001
2059
  body: net.body,
2002
2060
  });
2003
2061
  }
2004
- else if (net.protocol === 'iot') {
2005
- const token = await this.getIotToken(net.devices);
2006
- //物联网设备
2007
- if (net.method === 'mqtt') {
2008
- net.index = mqttIndex;
2009
- this.mqttClients[mqttIndex] = mqtt.connect(net.url);
2010
- this.mqttClients[mqttIndex].on('message', (topic, message) => {
2011
- this.socketCallback(message.toString(), {
2012
- topic: `le5le-iot/properties/${token}`,
2013
- type: 'iot',
2014
- url: net.url,
2015
- method: 'mqtt',
2016
- });
2017
- });
2018
- this.mqttClients[mqttIndex].on('error', (error) => {
2019
- this.store.emitter.emit('error', { type: 'mqtt', error });
2020
- });
2021
- this.mqttClients[mqttIndex].subscribe(`le5le-iot/properties/${token}`);
2022
- mqttIndex += 1;
2023
- }
2024
- else if (net.method === 'websocket') {
2025
- net.index = websocketIndex;
2026
- this.websockets[websocketIndex] = new WebSocket(`${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/api/ws/iot/properties`, token);
2027
- this.websockets[websocketIndex].onmessage = (e) => {
2028
- this.socketCallback(e.data, { type: 'iot', method: 'websocket' });
2029
- };
2030
- this.websockets[websocketIndex].onerror = (error) => {
2031
- this.store.emitter.emit('error', { type: 'websocket', error });
2032
- };
2033
- websocketIndex += 1;
2034
- }
2035
- }
2036
- else if (net.protocol === 'sql') {
2037
- await this.doSqlCode('list', net.dbId, net.sql);
2038
- if (net.interval) {
2039
- net.index = sqlIndex;
2040
- this.sqlTimerList[sqlIndex] = setInterval(async () => {
2041
- await this.doSqlCode('list', net.dbId, net.sql);
2042
- }, net.interval);
2043
- sqlIndex += 1;
2044
- }
2045
- }
2046
2062
  else if (net.protocol === 'ADIIOT') {
2047
2063
  connectJetLinks(this, net);
2048
2064
  }
2065
+ else if (net.protocol === 'SSE') {
2066
+ net.index = sseIndex;
2067
+ this.connectSSE(net);
2068
+ sseIndex += 1;
2069
+ }
2049
2070
  });
2050
2071
  }
2051
2072
  this.onNetworkConnect(https);
2073
+ this.connectIot();
2074
+ this.connectSqls();
2075
+ }
2076
+ iotMqttClient;
2077
+ iotTimer;
2078
+ iotWebsocketClient;
2079
+ async connectIot() {
2080
+ const { iot } = this.store.data;
2081
+ if (!(iot && iot?.devices?.length)) {
2082
+ return;
2083
+ }
2084
+ const url = globalThis.iotUrl || await this.getMqttUrl();
2085
+ if (!url) {
2086
+ console.warn('iot Request address error');
2087
+ return;
2088
+ }
2089
+ const token = await this.getIotToken(iot.devices, iot.protocol === 'websocket' ? 1 : undefined);
2090
+ //物联网设备
2091
+ // if(iot.protocol === 'mqtt'){
2092
+ // const url ='ws://192.168.110.148:8083/mqtt'; //`${location.protocol === 'https:'?'wss':'ws'}://${iot.host}:${location.protocol === 'https:'?'8084':'8083'}/mqtt`
2093
+ this.iotMqttClient = mqtt.connect(url);
2094
+ this.iotMqttClient.on('message', (topic, message) => {
2095
+ this.socketCallback(message.toString(), {
2096
+ topic: `le5le-iot/properties/${token}`,
2097
+ type: 'iot',
2098
+ url,
2099
+ method: 'mqtt'
2100
+ });
2101
+ });
2102
+ this.iotMqttClient.on('error', (error) => {
2103
+ this.store.emitter.emit('error', { type: 'mqtt', error });
2104
+ });
2105
+ this.iotMqttClient.subscribe(`le5le-iot/properties/${token}`);
2106
+ this.iotTimer = setInterval(() => {
2107
+ this.iotMqttClient && this.iotMqttClient.publish(`le5le-iot/subscribe/ping`, token);
2108
+ }, 300000);
2109
+ // }else if(iot.protocol === 'websocket'){
2110
+ // const url = 'ws://192.168.110.6/api/ws/iot/properties'// `${location.protocol === 'https:'?'wss':'ws'}://${location.host}/api/ws/iot/properties`
2111
+ // this.iotWebsocketClient = new WebSocket(
2112
+ // url,
2113
+ // token
2114
+ // );
2115
+ // this.iotWebsocketClient.onmessage = (e) => {
2116
+ // this.socketCallback(e.data, { type: 'iot', method: 'websocket' });
2117
+ // };
2118
+ // this.iotWebsocketClient.onerror = (error) => {
2119
+ // this.store.emitter.emit('error', { type: 'websocket', error });
2120
+ // };
2121
+ // }
2122
+ }
2123
+ // type SqlType = 'list' | 'get' | 'exec' | 'add' | 'update' | 'delete';
2124
+ connectSqls() {
2125
+ const { sqls } = this.store.data;
2126
+ if (sqls && sqls.length) {
2127
+ let sqlIndex = 0;
2128
+ sqls.forEach(async (sql) => {
2129
+ await this.doSqlCode(sql);
2130
+ if (sql.interval) {
2131
+ sql.index = sqlIndex;
2132
+ this.sqlTimerList[sqlIndex] = setInterval(async () => {
2133
+ await this.doSqlCode(sql);
2134
+ }, sql.interval);
2135
+ sqlIndex += 1;
2136
+ }
2137
+ });
2138
+ }
2139
+ }
2140
+ connectSSE(net) {
2141
+ this.eventSources[net.index] = new EventSource(net.url, { withCredentials: net.withCredentials });
2142
+ this.eventSources[net.index].onmessage = (e) => {
2143
+ this.socketCallback(e.data, { type: 'SSE', url: net.url });
2144
+ };
2145
+ this.eventSources[net.index].onerror = (error) => {
2146
+ this.store.emitter.emit('error', { type: 'SSE', error });
2147
+ };
2148
+ }
2149
+ closeSSE() {
2150
+ this.eventSources &&
2151
+ this.eventSources.forEach((es) => {
2152
+ if (es) {
2153
+ es.close();
2154
+ es = undefined;
2155
+ }
2156
+ });
2052
2157
  }
2053
2158
  connectNetWebSocket(net) {
2054
2159
  if (this.websockets[net.index]) {
@@ -2080,28 +2185,59 @@ export class Meta2d {
2080
2185
  }, 2000);
2081
2186
  };
2082
2187
  }
2083
- async getIotToken(devices) {
2188
+ async getMqttUrl() {
2189
+ const res = await fetch('/api/iot/app/mqtt', {
2190
+ method: 'GET',
2191
+ headers: {
2192
+ Authorization: `Bearer ${getToken()}`,
2193
+ },
2194
+ });
2195
+ if (res.ok) {
2196
+ const data = await res.text();
2197
+ let results = JSON.parse(data);
2198
+ let port = results.wssPort || results.wsPort;
2199
+ if (!port) {
2200
+ return;
2201
+ }
2202
+ return `${location.protocol === 'https:' ? 'wss' : 'ws'}://${results.host}:${location.protocol === 'https:' ? results.wssPort : results.wsPort}${results.path}`;
2203
+ }
2204
+ }
2205
+ async getIotToken(devices, type) {
2084
2206
  const res = await fetch('/api/iot/subscribe/properties', {
2085
2207
  method: 'POST',
2086
- body: JSON.stringify({ devices: devices }),
2208
+ headers: {
2209
+ Authorization: `Bearer ${getToken()}`,
2210
+ },
2211
+ body: JSON.stringify({ devices: devices, type }),
2087
2212
  });
2088
2213
  if (res.ok) {
2089
2214
  const data = await res.text();
2090
2215
  return JSON.parse(data).token;
2091
2216
  }
2092
2217
  }
2093
- async doSqlCode(type, dbid, sql) {
2094
- const res = await fetch(`/api/iot/data/sql/${type}`, {
2218
+ async doSqlCode(sql) {
2219
+ const method = sql.method || 'get';
2220
+ let _sql = sql.sql;
2221
+ if (method === 'list') {
2222
+ _sql += ` LIMIT ${sql.pageSize || 20}` + (sql.current > 1 ? (' OFFSET ' + (sql.current - 1) * sql.pageSize) : '');
2223
+ }
2224
+ const res = await fetch(`/api/iot/data/sql/${method}`, {
2095
2225
  method: 'POST',
2096
- body: JSON.stringify({ dbid, sql }),
2226
+ headers: {
2227
+ Authorization: `Bearer ${getCookie('token') || localStorage.getItem('token') || new URLSearchParams(location.search).get('token') || ''}`,
2228
+ },
2229
+ body: JSON.stringify({ dbid: sql.dbid, sql: _sql, }),
2097
2230
  });
2098
2231
  if (res.ok) {
2099
- const data = await res.text();
2232
+ let data = await res.text();
2100
2233
  if (data) {
2101
- this.socketCallback(data, {
2102
- type: 'sql',
2103
- url: `/api/iot/data/sql/${type}`,
2234
+ const arr = [];
2235
+ data = JSON.parse(data);
2236
+ sql.keys?.forEach((key) => {
2237
+ arr.push({ id: sql.bindId + '#' + key, value: getter(data, key.split('#').join('.')) });
2104
2238
  });
2239
+ arr.push({ id: sql.bindId, value: data });
2240
+ this.socketCallback(JSON.stringify(arr), { type: 'sql', url: `/api/iot/data/sql/${method}`, method });
2105
2241
  }
2106
2242
  }
2107
2243
  }
@@ -2436,7 +2572,19 @@ export class Meta2d {
2436
2572
  clearInterval(_sqlTimer);
2437
2573
  _sqlTimer = undefined;
2438
2574
  });
2575
+ if (this.iotMqttClient) {
2576
+ this.iotMqttClient.end();
2577
+ this.iotMqttClient = undefined;
2578
+ }
2579
+ clearInterval(this.iotTimer);
2580
+ this.iotTimer = undefined;
2581
+ // if(this.iotWebsocketClient){
2582
+ // this.iotWebsocketClient.onclose = undefined;
2583
+ // this.iotWebsocketClient.close();
2584
+ // this.iotWebsocketClient = undefined;
2585
+ // }
2439
2586
  closeJetLinks(this);
2587
+ this.closeSSE();
2440
2588
  }
2441
2589
  socketCallback(message, context) {
2442
2590
  this.store.emitter.emit('socket', { message, context });