@operato/scene-mpi 8.0.0-beta.1 → 8.0.0-beta.2

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/indicator.ts DELETED
@@ -1,638 +0,0 @@
1
- const IMAGE = new URL('../../icons/indicator.png', import.meta.url).href
2
-
3
- import { Component, ComponentNature, RectPath, Shape } from '@hatiolab/things-scene'
4
- import SegmentDisplay from './segment-display'
5
-
6
- import {
7
- onMouseDownMButton,
8
- onMouseDownFButton,
9
- onMouseDownCButton,
10
- onMouseDownBigButton
11
- } from './indicator-user-action'
12
-
13
- import { onmessage } from './indicator-on-message'
14
- import Gateway from './gateway'
15
-
16
- const NATURE: ComponentNature = {
17
- mutable: false,
18
- resizable: true,
19
- rotatable: true,
20
- properties: [
21
- {
22
- type: 'string',
23
- label: 'segment_role',
24
- name: 'segments'
25
- },
26
- {
27
- type: 'select',
28
- label: 'button_color',
29
- name: 'buttonColor',
30
- property: {
31
- options: [
32
- {
33
- display: 'BASIC',
34
- value: '#0000'
35
- },
36
- {
37
- display: 'YELLOW',
38
- value: '#ff0'
39
- },
40
- {
41
- display: 'GREEN',
42
- value: '#0f0'
43
- },
44
- {
45
- display: 'RED',
46
- value: '#f00'
47
- },
48
- {
49
- display: 'BLUE',
50
- value: '#00f'
51
- }
52
- ]
53
- }
54
- },
55
- {
56
- type: 'select',
57
- label: 'boot_flag',
58
- name: 'boot_flag',
59
- property: {
60
- options: [
61
- {
62
- display: '',
63
- value: ''
64
- },
65
- {
66
- display: 'TRUE',
67
- value: 'true'
68
- },
69
- {
70
- display: 'FALSE',
71
- value: 'false'
72
- }
73
- ]
74
- }
75
- },
76
- {
77
- type: 'select',
78
- label: 'reply_target',
79
- name: 'reply_target',
80
- property: {
81
- options: [
82
- {
83
- display: '',
84
- value: ''
85
- },
86
- {
87
- display: 'MQTT',
88
- value: 'MQTT'
89
- },
90
- {
91
- display: 'GraphQl',
92
- value: 'GraphQl'
93
- }
94
- ]
95
- }
96
- }
97
- ],
98
- help: 'scene/component/indicator'
99
- }
100
-
101
- const WIDTH = 449
102
- const HEIGHT = 53
103
-
104
- const RECT_BUTTON_EDGE = 3
105
-
106
- export default class Indicator extends RectPath(Shape) {
107
- lit = false
108
- ledLit = false
109
- store = {} as any
110
- conf = {
111
- seg_role: ['S', 'S'],
112
- alignment: 'R',
113
- btn_mode: 'S',
114
- btn_intvl: 5,
115
- bf_on_msg: '',
116
- bf_on_msg_t: 1,
117
- bf_on_delay: 1,
118
- cncl_delay: 10,
119
- blink_if_full: true,
120
- off_use_res: false,
121
- led_bar_mode: 'S',
122
- led_bar_intvl: 5,
123
- led_bar_brtns: 6
124
- } as any
125
- currentTask = 'ready'
126
- cookedData: any = {}
127
- readOnly?: boolean
128
- version?: any
129
-
130
- static _image: HTMLImageElement
131
-
132
- static get image() {
133
- if (!Indicator._image) {
134
- Indicator._image = new Image()
135
- Indicator._image.src = IMAGE
136
- }
137
-
138
- return Indicator._image
139
- }
140
-
141
- get colors(): { [key: string]: string } {
142
- return {
143
- R: '#f00',
144
- G: '#0f0',
145
- B: '#00f',
146
- C: '#0ff',
147
- M: '#f0f',
148
- Y: '#ff0',
149
- K: '#0000',
150
- W: '#fff'
151
- }
152
- }
153
-
154
- get btnModes() {
155
- return {
156
- BLINK: 'B', // 깜박
157
- ALWAYS: 'S' // 항상
158
- }
159
- }
160
-
161
- get tasks(): { [key: string]: string } {
162
- return {
163
- PICK: 'pick',
164
- STOCK: 'stock',
165
- FULL: 'full',
166
- MODIFY: 'modify',
167
- END: 'end',
168
- DISPLAY: 'display',
169
- READY: 'ready',
170
- STRSHOW: 'strshow'
171
- }
172
- }
173
-
174
- get alignmentOptions() {
175
- return {
176
- LEFT: 'L',
177
- RIGHT: 'R'
178
- }
179
- }
180
-
181
- get segmentRoles() {
182
- return {
183
- RELAY_SEQ: {
184
- INITIAL: 'R',
185
- KEY: 'org_relay'
186
- },
187
- BOXES: {
188
- INITIAL: 'B',
189
- KEY: 'org_box_qty'
190
- },
191
- PCS: {
192
- INITIAL: 'P',
193
- KEY: 'org_ea_qty'
194
- }
195
- }
196
- }
197
-
198
- get getConf() {
199
- return this.conf
200
- }
201
-
202
- set setConf(conf: any) {
203
- this.conf = conf
204
- }
205
-
206
- get gateway(): Gateway {
207
- return this.root.findFirst('gateway') as Gateway
208
- // var gateway = this.parent
209
- // while (gateway.constructor.name !== ('Gateway' || 'Window')) {
210
- // gateway = gateway.parent
211
- // }
212
-
213
- // if (gateway.constructor.name === 'Window') return
214
-
215
- // return gateway
216
- }
217
-
218
- get ledRect() {
219
- return this.parent.findFirst('rect') || {}
220
- }
221
-
222
- dispose() {
223
- super.dispose()
224
- }
225
-
226
- /**
227
- *
228
- * @param {array} args
229
- */
230
- setSegmentsState(args: any[]) {
231
- var stateArr: any[] = []
232
-
233
- var currentRole = this.store.seg_role ? this.store.seg_role : this.getConf.seg_role
234
- currentRole.forEach((role: any) => {
235
- var ele
236
- args.forEach(arg => {
237
- if (role == arg.role && (arg.value || arg.value >= 0)) {
238
- ele = arg.value
239
- }
240
- })
241
- stateArr.push(ele)
242
- })
243
- var stateStr = stateArr.join(',')
244
- this.setState('segments', stateStr)
245
- }
246
-
247
- /**
248
- *
249
- * @param {object} data
250
- */
251
- jobLightOn(data: any, lit = true) {
252
- var toutDisplayMessage = (indicator: Indicator) => {
253
- indicator.displayMessage(indicator.getConf.bf_on_msg, indicator.cookedData.buttonColor, false)
254
- setTimeout(() => {
255
- toutDelayBeforeLightOn(indicator)
256
- }, indicator.getConf.bf_on_msg_t * 100)
257
- }
258
-
259
- var toutDelayBeforeLightOn = (indicator: Indicator) => {
260
- indicator.lightOff()
261
- setTimeout(() => {
262
- indicator.lightOn(data, lit)
263
- }, indicator.getConf.bf_on_delay * 100)
264
- }
265
-
266
- if (typeof this.getConf.bf_on_msg === 'string' && this.getConf.bf_on_msg.length > 0) {
267
- toutDisplayMessage(this)
268
- } else if (this.getConf.bf_on_delay > 0) {
269
- toutDelayBeforeLightOn(this)
270
- } else {
271
- this.lightOn(data, lit)
272
- }
273
- }
274
-
275
- /**
276
- *
277
- * @param {object} data
278
- */
279
- lightOn(data: any, lit = true) {
280
- var sublen = 6 / this.getConf.seg_role.length
281
- switch (this.getConf.alignment) {
282
- case this.alignmentOptions.LEFT:
283
- {
284
- let arr: any[] = []
285
- Object.values(this.segmentRoles).forEach(role => {
286
- if (data[role.KEY] || data[role.KEY] >= 0) {
287
- var obj = {
288
- role: role.INITIAL,
289
- value: data[role.KEY]
290
- }
291
- arr.push(obj)
292
- }
293
- })
294
- this.setSegmentsState(arr)
295
- }
296
- break
297
- case this.alignmentOptions.RIGHT:
298
- default:
299
- {
300
- let arr: any[] = []
301
- Object.values(this.segmentRoles).forEach(role => {
302
- if (data[role.KEY] || data[role.KEY] >= 0) {
303
- var obj = {
304
- role: role.INITIAL,
305
- value: (' ' + data[role.KEY]).substr(-sublen)
306
- }
307
- arr.push(obj)
308
- }
309
- })
310
- this.setSegmentsState(arr)
311
- }
312
- break
313
- }
314
- if (data.buttonColor) this.setState('buttonColor', String(data.buttonColor))
315
- this.lit = lit
316
- }
317
-
318
- lightOff() {
319
- this.setState('segments', this.displays.length == 3 ? ',,' : ',')
320
- this.setState('buttonColor', '#0000')
321
-
322
- this.lit = false
323
- }
324
-
325
- /**
326
- *
327
- * @param {string} msg
328
- * @param {string} color
329
- */
330
- displayMessage(msg: string, color = 'K', lit = true) {
331
- var eachSegLen = this.displays[0].pattern.length
332
- var allSegLen = eachSegLen * this.displays.length
333
-
334
- var d = msg || this.getConf.bf_on_msg
335
-
336
- switch (this.conf.alignment) {
337
- case this.alignmentOptions.LEFT:
338
- {
339
- d = (d + ' ').substr(0, allSegLen)
340
- }
341
- break
342
- case this.alignmentOptions.RIGHT:
343
- default:
344
- {
345
- d = (' ' + d).substr(-allSegLen)
346
- }
347
- break
348
- }
349
-
350
- var da = []
351
-
352
- var i = 1
353
- var startIdx = 0
354
- while (i <= allSegLen) {
355
- if (i % eachSegLen == 0) {
356
- da.push(d.substr(startIdx, eachSegLen))
357
- startIdx = i
358
- }
359
- i++
360
- }
361
- this.setState('segments', da.join(','))
362
- this.setState('buttonColor', this.colors[color])
363
- this.lit = lit
364
- }
365
-
366
- rectButtonContains(x: number, y: number, WRATE: number, HRATE: number) {
367
- var left = 310 * WRATE
368
- var top = 8 * HRATE
369
- var width = 62 * WRATE
370
- var height = 36 * HRATE
371
-
372
- var extend = RECT_BUTTON_EDGE
373
-
374
- return (
375
- x < Math.max(left + width, left) + extend &&
376
- x > Math.min(left + width, left) - extend &&
377
- y < Math.max(top + height, top) + extend &&
378
- y > Math.min(top + height, top) - extend
379
- )
380
- }
381
-
382
- mfcButtonContains(x: number, y: number, WRATE: number, HRATE: number) {
383
- var left = 38 * WRATE
384
- var top = 14 * HRATE
385
- var width = 17 * WRATE
386
- var height = 25 * HRATE
387
-
388
- var extend = RECT_BUTTON_EDGE
389
- if (
390
- x < Math.max(left + width, left) + extend &&
391
- x > Math.min(left + width, left) - extend &&
392
- y < Math.max(top + height, top) + extend &&
393
- y > Math.min(top + height, top) - extend
394
- ) {
395
- return 'M'
396
- }
397
-
398
- var rx = 9 * WRATE
399
- var ry = 9 * HRATE
400
- var cx = 70 * WRATE
401
- var cy = 17 * HRATE
402
- var normx = (x - cx) / (rx * 2 - 0.5)
403
- var normy = (y - cy) / (ry * 2 - 0.5)
404
-
405
- if (normx * normx + normy * normy < 0.25) {
406
- return 'F'
407
- }
408
-
409
- cx = 70 * WRATE
410
- cy = 39 * HRATE
411
- normx = (x - cx) / (rx * 2 - 0.5)
412
- normy = (y - cy) / (ry * 2 - 0.5)
413
-
414
- if (normx * normx + normy * normy < 0.25) {
415
- return 'C'
416
- }
417
- }
418
-
419
- onmousedown(e: MouseEvent, hint: any) {
420
- var { left, top, width, height } = this.bounds
421
-
422
- var WRATE = width / WIDTH
423
- var HRATE = height / HEIGHT
424
-
425
- var { x, y } = this.transcoordC2S(e.offsetX, e.offsetY)
426
-
427
- if (this.rectButtonContains(x - left, y - top, WRATE, HRATE)) {
428
- onMouseDownBigButton(this)
429
- } else {
430
- switch (this.mfcButtonContains(x - left, y - top, WRATE, HRATE)) {
431
- case 'M':
432
- onMouseDownMButton(this)
433
- break
434
- case 'F':
435
- onMouseDownFButton(this)
436
- break
437
- case 'C':
438
- onMouseDownCButton(this)
439
- break
440
- default:
441
- }
442
- }
443
- }
444
-
445
- get displays() {
446
- var { width, height } = this.bounds
447
-
448
- var WRATE = width / WIDTH
449
- var HRATE = height / HEIGHT
450
-
451
- var { segments = new Array(this.getConf.seg_role.length).join(',') } = this.state
452
-
453
- return (segments as string).split(',', 3).map((value, idx, array) => {
454
- var display = new SegmentDisplay(63 * WRATE, 28 * HRATE)
455
-
456
- display.pattern = array.length == 2 ? '###' : array.length == 3 ? '##' : '###' // 3 넘는 건 안 함
457
- display.displayAngle = 8
458
- display.digitHeight = 20
459
- display.digitWidth = 11
460
- display.digitDistance = 6
461
- display.segmentWidth = 2.5
462
- display.segmentDistance = 0.2
463
- display.segmentCount = SegmentDisplay.SevenSegment
464
- display.cornerType = SegmentDisplay.SymmetricCorner
465
- display.colorOn = idx == 0 ? '#007dfe' : idx == 1 ? '#fd0000' : '#fee400'
466
- display.colorOff = '#2c2c2c'
467
-
468
- display.setValue(value)
469
-
470
- return display
471
- })
472
- }
473
-
474
- _drawRectButton(context: CanvasRenderingContext2D, WRATE: number, HRATE: number, color: string) {
475
- var w = 62 * WRATE
476
- var h = 36 * HRATE
477
- var r = Math.min(7 * WRATE, 7 * HRATE)
478
- var edge = Math.floor(r / 2)
479
- var highlight = Math.floor(r / 5)
480
-
481
- if (w < 2 * r) r = w / 2
482
- if (h < 2 * r) r = h / 2
483
-
484
- context.beginPath()
485
- context.moveTo(r, 0)
486
- context.arcTo(w, 0, w, h, r)
487
- context.arcTo(w, h, 0, h, r)
488
- context.arcTo(0, h, 0, 0, r)
489
- context.arcTo(0, 0, w, 0, r)
490
-
491
- context.globalAlpha = 1
492
- context.fillStyle = color
493
- context.strokeStyle = color
494
- context.lineWidth = edge - 2
495
- context.fill()
496
- context.stroke()
497
- context.strokeStyle = 'black'
498
- context.globalAlpha = 0.3
499
- context.stroke()
500
-
501
- context.beginPath()
502
- context.moveTo(highlight, h - r)
503
- context.arcTo(highlight, highlight, r, highlight, r - highlight)
504
- context.lineTo(w - r, highlight)
505
- context.strokeStyle = 'white'
506
- context.globalAlpha = 0.6
507
- context.lineWidth = highlight
508
- context.stroke()
509
-
510
- context.beginPath()
511
- context.moveTo(w - r, highlight)
512
- context.arcTo(w - highlight, highlight, w - highlight, r, r - highlight)
513
- context.arcTo(w - highlight, h - highlight, w - r, h - highlight, r - highlight)
514
- context.arcTo(highlight, h - highlight, highlight, h - r, r - highlight)
515
-
516
- context.strokeStyle = 'white'
517
- context.globalAlpha = 0.4
518
- context.lineWidth = highlight
519
- context.stroke()
520
-
521
- context.globalAlpha = 1
522
- }
523
-
524
- _drawMFCButton(context: CanvasRenderingContext2D, WRATE: number, HRATE: number) {
525
- context.textAlign = 'center'
526
- context.textBaseline = 'middle'
527
- context.font = `${Math.min(13 * WRATE, 13 * HRATE)}px Arial`
528
-
529
- context.lineJoin = 'round'
530
- var r = Math.min(7 * WRATE, 7 * HRATE)
531
- var edge = Math.floor(r / 3)
532
- // console.log('r', r, 'wrate', WRATE, 'hrate', HRATE, 'edge', edge)
533
- context.lineWidth = edge
534
-
535
- context.beginPath()
536
- // context.ellipse(96 * WRATE, 27 * HRATE, 7 * WRATE, 7 * HRATE, 0, 0, 2 * Math.PI)
537
- context.fillStyle = 'rgba(255, 0, 0, 0.0)'
538
- context.strokeStyle = 'rgba(255, 0, 0, 0.0)'
539
- context.strokeRect(38 * WRATE, 14 * HRATE, 17 * WRATE, 25 * HRATE)
540
- context.fillRect(38 * WRATE, 14 * HRATE, 17 * WRATE, 25 * HRATE)
541
- context.fill()
542
-
543
- // context.fillStyle = 'black'
544
- // context.fillText('M', 40 * WRATE, 27 * HRATE)
545
-
546
- context.beginPath()
547
- context.ellipse(70 * WRATE, 15 * HRATE, 9 * WRATE, 9 * HRATE, 0, 0, 2 * Math.PI)
548
- context.fillStyle = 'rgba(255, 0, 0, 0.0)'
549
- context.fill()
550
-
551
- // context.fillStyle = 'white'
552
- // context.fillText('F', 70 * WRATE, 17 * HRATE)
553
-
554
- context.beginPath()
555
- context.ellipse(70 * WRATE, 39 * HRATE, 9 * WRATE, 9 * HRATE, 0, 0, 2 * Math.PI)
556
- context.fillStyle = 'rgba(255, 0, 0, 0.0)'
557
- context.fill()
558
-
559
- // context.fillStyle = 'white'
560
- // context.fillText('C', 70 * WRATE, 39 * HRATE)
561
- }
562
-
563
- render(context: CanvasRenderingContext2D) {
564
- var { left, top, width, height } = this.bounds
565
-
566
- var color = this.state.buttonColor || '#0000'
567
-
568
- var WRATE = width / WIDTH
569
- var HRATE = height / HEIGHT
570
-
571
- context.translate(left, top)
572
- context.save()
573
-
574
- context.beginPath()
575
- this.drawImage(context, Indicator.image, 0, 0, width, height)
576
-
577
- this._drawMFCButton(context, WRATE, HRATE)
578
-
579
- var displays = this.displays
580
-
581
- var myCursor = displays.length == 3 ? 1 : 0
582
-
583
- context.translate((135 - myCursor * 12) * WRATE, 12 * HRATE)
584
- displays[0].draw(context)
585
-
586
- if (displays.length >= 2) {
587
- context.translate((75 - myCursor * 25) * WRATE, 0)
588
- displays[1].draw(context)
589
- }
590
-
591
- if (displays.length >= 3) {
592
- context.translate((75 - myCursor * 25) * WRATE, 0)
593
- displays[2].draw(context)
594
- }
595
-
596
- context.beginPath()
597
-
598
- context.restore()
599
- context.translate(310 * WRATE, 8 * HRATE)
600
- this._drawRectButton(context, WRATE, HRATE, color)
601
-
602
- context.beginPath()
603
- }
604
-
605
- onchangeData(after: any, before: any) {
606
- super.onchangeData(after, before)
607
-
608
- onmessage(this, after.data)
609
- }
610
-
611
- get hasTextProperty() {
612
- return false
613
- }
614
-
615
- get nature() {
616
- return NATURE
617
- }
618
-
619
- onButton() {
620
- switch (this.currentTask) {
621
- case this.tasks.END:
622
- {
623
- // onMouseDownFButton(this);
624
- }
625
- break
626
- case this.tasks.DISPLAY: {
627
- return
628
- }
629
- default:
630
- {
631
- onMouseDownBigButton(this)
632
- }
633
- break
634
- }
635
- }
636
- }
637
-
638
- Component.register('indicator', Indicator)
@@ -1,88 +0,0 @@
1
- const reply = new URL('../../icons/reply-button.png', import.meta.url).href
2
-
3
- import { Component, ComponentNature, RectPath, Shape } from '@hatiolab/things-scene'
4
-
5
- import { consoleLogger } from './gateway-on-message'
6
- import Gateway from './gateway'
7
-
8
- export const buttons = [
9
- {
10
- icon: reply,
11
- handler: onClickReply
12
- }
13
- ]
14
-
15
- const NATURE: ComponentNature = {
16
- mutable: false,
17
- resizable: true,
18
- rotatable: true,
19
- properties: [
20
- {
21
- type: 'string',
22
- name: 'publisher',
23
- label: 'publisher'
24
- }
25
- ],
26
- help: 'scene/component/reply-button'
27
- }
28
-
29
- export default class ReplyButton extends RectPath(Shape) {
30
- static _image?: HTMLImageElement
31
-
32
- static get image() {
33
- if (!ReplyButton._image) {
34
- ReplyButton._image = new Image()
35
- ReplyButton._image.src = reply
36
- }
37
-
38
- return ReplyButton._image
39
- }
40
-
41
- get publisher() {
42
- if (this.state.publisher) {
43
- return this.root.findById(this.state.publisher)
44
- }
45
- }
46
-
47
- render(context: CanvasRenderingContext2D) {
48
- var { left, top, width, height } = this.bounds
49
-
50
- context.beginPath()
51
-
52
- context.rect(left, top, width, height)
53
-
54
- this.drawFill(context)
55
- this.drawStroke(context)
56
-
57
- this.drawImage(context, ReplyButton.image, left, top, width, height)
58
- }
59
-
60
- onmousedown(e: MouseEvent, hint: any) {
61
- var button = this.buttonContains()
62
- if (button) {
63
- button.handler(this)
64
- }
65
- }
66
-
67
- buttonContains() {
68
- return buttons[0]
69
- }
70
-
71
- get nature() {
72
- return NATURE
73
- }
74
- }
75
-
76
- function onClickReply(button: Component) {
77
- consoleLogger('onClickReply')
78
-
79
- var gateways = button.root.findAll('gateway') as Gateway[]
80
-
81
- gateways.forEach((gw, index) => {
82
- gw.indicators.forEach(ind => {
83
- ind.onButton()
84
- })
85
- })
86
- }
87
-
88
- Component.register('reply-button', ReplyButton)