@cpzxrobot/sdk 1.2.85 → 1.2.86
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/device_gateway.ts +8 -0
- package/dist/device_gateway.js +4 -0
- package/dist/index.js +91 -1
- package/index.ts +103 -3
- package/package.json +1 -1
- package/types.d.ts +1 -0
package/device_gateway.ts
CHANGED
|
@@ -208,6 +208,14 @@ export class DeviceGateway extends Object {
|
|
|
208
208
|
this.context.showInDeviceManager(id,type);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
async watch(
|
|
212
|
+
id: number,
|
|
213
|
+
fn: any,
|
|
214
|
+
) {
|
|
215
|
+
var axios = await this.context.ready;
|
|
216
|
+
return axios.getAsSse(`/api/v2/device/watch/${id}`, fn)
|
|
217
|
+
}
|
|
218
|
+
|
|
211
219
|
private getFilter<T extends { id: number }>(
|
|
212
220
|
type: string,
|
|
213
221
|
cls: new (context: Cpzxrobot) => DeviceFilter<T>
|
package/dist/device_gateway.js
CHANGED
|
@@ -159,6 +159,10 @@ class DeviceGateway extends Object {
|
|
|
159
159
|
show(id, type = "datapoint") {
|
|
160
160
|
this.context.showInDeviceManager(id, type);
|
|
161
161
|
}
|
|
162
|
+
async watch(id, fn) {
|
|
163
|
+
var axios = await this.context.ready;
|
|
164
|
+
return axios.getAsSse(`/api/v2/device/watch/${id}`, fn);
|
|
165
|
+
}
|
|
162
166
|
getFilter(type, cls) {
|
|
163
167
|
// 如果filters中已经有对应type的过滤器,则直接返回该过滤器
|
|
164
168
|
if (this.filters.has(type)) {
|
package/dist/index.js
CHANGED
|
@@ -108,6 +108,49 @@ class Cpzxrobot {
|
|
|
108
108
|
}
|
|
109
109
|
return response;
|
|
110
110
|
};
|
|
111
|
+
const streamWithAuth = async (input, init, fn) => {
|
|
112
|
+
const headers = new Headers(init === null || init === void 0 ? void 0 : init.headers);
|
|
113
|
+
headers.set('Authorization', this.token);
|
|
114
|
+
const response = await fetch(baseURL + input.toString(), Object.assign(Object.assign({}, init), { headers }));
|
|
115
|
+
var reader = response.body.getReader();
|
|
116
|
+
const decoder = new TextDecoder("utf-8");
|
|
117
|
+
let done = false;
|
|
118
|
+
var buf = "";
|
|
119
|
+
while (!done) {
|
|
120
|
+
const { value, done } = await reader.read();
|
|
121
|
+
if (done) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
const chunkValue = decoder.decode(value);
|
|
125
|
+
//split value to lines
|
|
126
|
+
// 将值拆分为行
|
|
127
|
+
buf = buf + chunkValue;
|
|
128
|
+
var i = buf.indexOf("\n");
|
|
129
|
+
while (i > -1) {
|
|
130
|
+
//find first \n
|
|
131
|
+
var line = buf.substring(0, i);
|
|
132
|
+
try {
|
|
133
|
+
if (line === "[DONE]") {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// remove prefix 'data: '
|
|
138
|
+
// 移除前缀 'data: '
|
|
139
|
+
var data = JSON.parse(line.split(": ")[1]);
|
|
140
|
+
//{"choices":[{"delta":{"content":" </"},"index":0}],"created":1741749068,"id":"chatcmpl-67ccb889154043f5874cbf3a64ec163e","model":"DeepSeek-R1","object":"chat.completion.chunk"}
|
|
141
|
+
fn === null || fn === void 0 ? void 0 : fn.call(data);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
console.error("解析失败", e);
|
|
146
|
+
}
|
|
147
|
+
buf = buf.substring(i + 1);
|
|
148
|
+
i = buf.indexOf("\n");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
;
|
|
152
|
+
return true;
|
|
153
|
+
};
|
|
111
154
|
const processQueryParams = (url, config) => {
|
|
112
155
|
if (config && config.params) {
|
|
113
156
|
const flattenParams = (params, prefix = '') => {
|
|
@@ -155,7 +198,27 @@ class Cpzxrobot {
|
|
|
155
198
|
headers: config === null || config === void 0 ? void 0 : config.headers
|
|
156
199
|
});
|
|
157
200
|
const blob = await response.blob();
|
|
158
|
-
|
|
201
|
+
// 文件名解析逻辑
|
|
202
|
+
const contentDisposition = response.headers.get('Content-Disposition');
|
|
203
|
+
let filename = (_a = config === null || config === void 0 ? void 0 : config.fileName) !== null && _a !== void 0 ? _a : ""; // 默认文件名
|
|
204
|
+
// 1. 优先使用响应头中的文件名
|
|
205
|
+
if (filename == "") {
|
|
206
|
+
if (contentDisposition) {
|
|
207
|
+
const utf8FilenameMatch = contentDisposition.match(/filename\*=UTF-8''(.+)/i);
|
|
208
|
+
if (utf8FilenameMatch) {
|
|
209
|
+
filename = decodeURIComponent(utf8FilenameMatch[1]);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
const filenameMatch = contentDisposition.match(/filename="?(.+?)"?(;|$)/i);
|
|
213
|
+
if (filenameMatch)
|
|
214
|
+
filename = filenameMatch[1];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
filename = "file";
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
await this.saveBlob(blob, filename);
|
|
159
222
|
return { data: blob };
|
|
160
223
|
},
|
|
161
224
|
getAndPreview: async (url, config) => {
|
|
@@ -198,6 +261,13 @@ class Cpzxrobot {
|
|
|
198
261
|
}
|
|
199
262
|
};
|
|
200
263
|
});
|
|
264
|
+
},
|
|
265
|
+
getAsSse: (url, fn, config) => {
|
|
266
|
+
return new Promise((resolve, reject) => {
|
|
267
|
+
streamWithAuth(url, {
|
|
268
|
+
method: 'GET',
|
|
269
|
+
}, fn);
|
|
270
|
+
});
|
|
201
271
|
}
|
|
202
272
|
};
|
|
203
273
|
// @ts-ignore
|
|
@@ -266,6 +336,7 @@ class Cpzxrobot {
|
|
|
266
336
|
const platform =
|
|
267
337
|
// @ts-ignore
|
|
268
338
|
window.flutter_inappwebview;
|
|
339
|
+
var that = this;
|
|
269
340
|
this._getSelectedFarmFromMiniApp = function () {
|
|
270
341
|
return platform.callHandler("getSelectedFarmFromMiniApp");
|
|
271
342
|
};
|
|
@@ -338,6 +409,12 @@ class Cpzxrobot {
|
|
|
338
409
|
upload: function (url, option) {
|
|
339
410
|
return platform.callHandler("axios_upload", url, option);
|
|
340
411
|
},
|
|
412
|
+
getAsSse: async function (url, fn, config) {
|
|
413
|
+
var randomId = Math.random().toString(36).substring(2);
|
|
414
|
+
that.sseCallbacks[randomId] = fn;
|
|
415
|
+
await platform.callHandler("axios_getAsSse", url, config, randomId);
|
|
416
|
+
delete that.sseCallbacks[randomId];
|
|
417
|
+
},
|
|
341
418
|
};
|
|
342
419
|
if (
|
|
343
420
|
// @ts-ignore
|
|
@@ -358,6 +435,19 @@ class Cpzxrobot {
|
|
|
358
435
|
}, 1500);
|
|
359
436
|
});
|
|
360
437
|
}
|
|
438
|
+
window.addEventListener('message', (event) => {
|
|
439
|
+
if (event.data == 'capturePort') {
|
|
440
|
+
if (event.ports[0] != null) {
|
|
441
|
+
this.messagePort = event.ports[0];
|
|
442
|
+
this.messagePort.onmessage = (event) => {
|
|
443
|
+
if (event.data.id != undefined) {
|
|
444
|
+
var callback = this.sseCallbacks[event.data.id];
|
|
445
|
+
callback(event.data);
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}, false);
|
|
361
451
|
}
|
|
362
452
|
else {
|
|
363
453
|
if (this.isLocalDomain(domain)) {
|
package/index.ts
CHANGED
|
@@ -43,6 +43,7 @@ export class Cpzxrobot {
|
|
|
43
43
|
rejectReady!: (reason?: any) => void;
|
|
44
44
|
transport: TransportGateway;
|
|
45
45
|
platformReady!: Promise<boolean>;
|
|
46
|
+
messagePort!: MessagePort;
|
|
46
47
|
_getSelectedFarmFromMiniApp!: () => any;
|
|
47
48
|
_getSelectedUnitFromMiniApp!: () => any;
|
|
48
49
|
_jumpToMiniApp!: (url: string) => any;
|
|
@@ -78,6 +79,7 @@ export class Cpzxrobot {
|
|
|
78
79
|
ai: AiGateway = new AiGateway(this);
|
|
79
80
|
construction: ConstructionGateway = new ConstructionGateway(this);
|
|
80
81
|
system: SystemGateway = new SystemGateway(this);
|
|
82
|
+
sseCallbacks: any;
|
|
81
83
|
|
|
82
84
|
|
|
83
85
|
constructor(appCode: string) {
|
|
@@ -127,6 +129,53 @@ export class Cpzxrobot {
|
|
|
127
129
|
return response;
|
|
128
130
|
};
|
|
129
131
|
|
|
132
|
+
const streamWithAuth = async (input: RequestInfo, init?: RequestInit, fn?: Function) => {
|
|
133
|
+
const headers = new Headers(init?.headers);
|
|
134
|
+
headers.set('Authorization', this.token);
|
|
135
|
+
const response = await fetch(baseURL + input.toString(), {
|
|
136
|
+
...init,
|
|
137
|
+
headers
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
var reader = response.body!.getReader();
|
|
141
|
+
const decoder = new TextDecoder("utf-8");
|
|
142
|
+
let done = false;
|
|
143
|
+
var buf: string = "";
|
|
144
|
+
while (!done) {
|
|
145
|
+
const { value, done } = await reader.read();
|
|
146
|
+
if (done) {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
const chunkValue = decoder.decode(value);
|
|
150
|
+
|
|
151
|
+
//split value to lines
|
|
152
|
+
// 将值拆分为行
|
|
153
|
+
buf = buf + chunkValue;
|
|
154
|
+
var i = buf.indexOf("\n");
|
|
155
|
+
while (i > -1) {
|
|
156
|
+
//find first \n
|
|
157
|
+
var line = buf.substring(0, i);
|
|
158
|
+
try {
|
|
159
|
+
if (line === "[DONE]") {
|
|
160
|
+
break;
|
|
161
|
+
} else {
|
|
162
|
+
// remove prefix 'data: '
|
|
163
|
+
// 移除前缀 'data: '
|
|
164
|
+
var data = JSON.parse(line.split(": ")[1]);
|
|
165
|
+
//{"choices":[{"delta":{"content":" </"},"index":0}],"created":1741749068,"id":"chatcmpl-67ccb889154043f5874cbf3a64ec163e","model":"DeepSeek-R1","object":"chat.completion.chunk"}
|
|
166
|
+
fn?.call(data);
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
console.error("解析失败", e);
|
|
170
|
+
}
|
|
171
|
+
buf = buf.substring(i + 1);
|
|
172
|
+
i = buf.indexOf("\n");
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
return true;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
|
|
130
179
|
const processQueryParams = (url: string, config?: any) => {
|
|
131
180
|
if (config && config.params) {
|
|
132
181
|
const flattenParams = (params: any, prefix = '') => {
|
|
@@ -177,7 +226,27 @@ export class Cpzxrobot {
|
|
|
177
226
|
headers: config?.headers
|
|
178
227
|
});
|
|
179
228
|
const blob = await response.blob();
|
|
180
|
-
|
|
229
|
+
|
|
230
|
+
// 文件名解析逻辑
|
|
231
|
+
const contentDisposition = response.headers.get('Content-Disposition');
|
|
232
|
+
let filename = config?.fileName ?? ""; // 默认文件名
|
|
233
|
+
|
|
234
|
+
// 1. 优先使用响应头中的文件名
|
|
235
|
+
if (filename == "") {
|
|
236
|
+
if (contentDisposition) {
|
|
237
|
+
const utf8FilenameMatch = contentDisposition.match(/filename\*=UTF-8''(.+)/i);
|
|
238
|
+
if (utf8FilenameMatch) {
|
|
239
|
+
filename = decodeURIComponent(utf8FilenameMatch[1]);
|
|
240
|
+
} else {
|
|
241
|
+
const filenameMatch = contentDisposition.match(/filename="?(.+?)"?(;|$)/i);
|
|
242
|
+
if (filenameMatch) filename = filenameMatch[1];
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
filename = "file"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
await this.saveBlob(blob, filename);
|
|
181
250
|
return { data: blob };
|
|
182
251
|
},
|
|
183
252
|
getAndPreview: async (url: string, config?: {
|
|
@@ -222,6 +291,17 @@ export class Cpzxrobot {
|
|
|
222
291
|
}
|
|
223
292
|
};
|
|
224
293
|
});
|
|
294
|
+
},
|
|
295
|
+
getAsSse: (url: string, fn: any, config?: {
|
|
296
|
+
fileName?: string;
|
|
297
|
+
params?: any;
|
|
298
|
+
preview?: boolean;
|
|
299
|
+
}) => {
|
|
300
|
+
return new Promise<any>((resolve, reject) => {
|
|
301
|
+
streamWithAuth(url, {
|
|
302
|
+
method: 'GET',
|
|
303
|
+
}, fn);
|
|
304
|
+
});
|
|
225
305
|
}
|
|
226
306
|
};
|
|
227
307
|
// @ts-ignore
|
|
@@ -295,6 +375,7 @@ export class Cpzxrobot {
|
|
|
295
375
|
} =
|
|
296
376
|
// @ts-ignore
|
|
297
377
|
window.flutter_inappwebview;
|
|
378
|
+
var that = this;
|
|
298
379
|
this._getSelectedFarmFromMiniApp = function () {
|
|
299
380
|
return platform.callHandler("getSelectedFarmFromMiniApp");
|
|
300
381
|
};
|
|
@@ -356,10 +437,10 @@ export class Cpzxrobot {
|
|
|
356
437
|
return platform.callHandler("axios_getAndSave", url, config);
|
|
357
438
|
},
|
|
358
439
|
getAndPreview: function (url, config) {
|
|
359
|
-
if (config== undefined){
|
|
440
|
+
if (config == undefined) {
|
|
360
441
|
config = {};
|
|
361
442
|
}
|
|
362
|
-
if (config.preview == undefined){
|
|
443
|
+
if (config.preview == undefined) {
|
|
363
444
|
config.preview = true;
|
|
364
445
|
}
|
|
365
446
|
return platform.callHandler("axios_getAndSave", url, config);
|
|
@@ -367,6 +448,12 @@ export class Cpzxrobot {
|
|
|
367
448
|
upload: function (url, option) {
|
|
368
449
|
return platform.callHandler("axios_upload", url, option);
|
|
369
450
|
},
|
|
451
|
+
getAsSse: async function (url, fn, config?) {
|
|
452
|
+
var randomId = Math.random().toString(36).substring(2);
|
|
453
|
+
that.sseCallbacks[randomId] = fn;
|
|
454
|
+
await platform.callHandler("axios_getAsSse", url, config, randomId);
|
|
455
|
+
delete that.sseCallbacks[randomId];
|
|
456
|
+
},
|
|
370
457
|
};
|
|
371
458
|
if (
|
|
372
459
|
// @ts-ignore
|
|
@@ -390,6 +477,19 @@ export class Cpzxrobot {
|
|
|
390
477
|
}, 1500);
|
|
391
478
|
});
|
|
392
479
|
}
|
|
480
|
+
window.addEventListener('message', (event) => {
|
|
481
|
+
if (event.data == 'capturePort') {
|
|
482
|
+
if (event.ports[0] != null) {
|
|
483
|
+
this.messagePort = event.ports[0];
|
|
484
|
+
this.messagePort.onmessage = (event) => {
|
|
485
|
+
if (event.data.id != undefined) {
|
|
486
|
+
var callback = this.sseCallbacks[event.data.id];
|
|
487
|
+
callback(event.data);
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}, false);
|
|
393
493
|
} else {
|
|
394
494
|
if (this.isLocalDomain(domain)) {
|
|
395
495
|
this.mode = "dev";
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -300,6 +300,7 @@ interface MyAxiosInstance {
|
|
|
300
300
|
//option.fileField:上传的文件字段名,默认为file
|
|
301
301
|
//option.data:上传的数据,例如{id:123,name:"xxx"},文件会被附加到data中,作为文件字段上传
|
|
302
302
|
upload: (url: string, option?: {}) => Promise<any>;
|
|
303
|
+
getAsSse: (url: string, fn: any, config?: any) => Promise<any>;
|
|
303
304
|
}
|
|
304
305
|
|
|
305
306
|
interface Assistant {
|