@things-factory/integration-melsec 8.0.0 → 9.0.0-beta.3
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/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/server/engine/connector/index.ts +0 -1
- package/server/engine/connector/melsec-plc.ts +0 -211
- package/server/engine/index.ts +0 -2
- package/server/engine/task/index.ts +0 -5
- package/server/engine/task/melsec-read-coil.ts +0 -61
- package/server/engine/task/melsec-read-word.ts +0 -60
- package/server/engine/task/melsec-wait-coil.ts +0 -80
- package/server/engine/task/melsec-write-coil.ts +0 -99
- package/server/engine/task/melsec-write-word.ts +0 -81
- package/server/index.ts +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/integration-melsec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0-beta.3",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"clean": "npm run clean:server"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@things-factory/integration-base": "^
|
|
26
|
+
"@things-factory/integration-base": "^9.0.0-beta.3",
|
|
27
27
|
"p-queue": "^6.4.0"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "1d7e0dd4c88f3c3f3bd311c00e4b1d1542d53634"
|
|
30
30
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './melsec-plc'
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import net from 'net'
|
|
2
|
-
import PromiseSocket from 'promise-socket'
|
|
3
|
-
import PQueue from 'p-queue'
|
|
4
|
-
import { sleep } from '@things-factory/utils'
|
|
5
|
-
|
|
6
|
-
import { ConnectionManager, Connector, Connection } from '@things-factory/integration-base'
|
|
7
|
-
|
|
8
|
-
const subHeader = '5000'
|
|
9
|
-
const networkNumber = '00'
|
|
10
|
-
const requireNumber = 'FF'
|
|
11
|
-
const requireIoNumber = '03FF'
|
|
12
|
-
const requireMultiNumber = '00'
|
|
13
|
-
const readrequireLength = '0018'
|
|
14
|
-
const writerequireLength = '0019'
|
|
15
|
-
const writewordrequireLength = '001C'
|
|
16
|
-
const reserve = '0000'
|
|
17
|
-
const readCommand = '0401'
|
|
18
|
-
const readWordSubCommand = '0000'
|
|
19
|
-
const readCoilSubCommand = '0001'
|
|
20
|
-
const writeCommand = '1401'
|
|
21
|
-
const writeWordSubCommand = '0000'
|
|
22
|
-
const writeSubCommand = '0001'
|
|
23
|
-
const readLengthDevice = '0001'
|
|
24
|
-
const writeLengthDevice = '0001'
|
|
25
|
-
|
|
26
|
-
export class MelsecPLCConnector implements Connector {
|
|
27
|
-
static getWriteCoilCommand(deviceCode, writeStartDevice, writeCoilValue, writeLength) {
|
|
28
|
-
if (writeLength) {
|
|
29
|
-
writeLength = writeLength.toString().padStart(4, '0')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
subHeader +
|
|
34
|
-
networkNumber +
|
|
35
|
-
requireNumber +
|
|
36
|
-
requireIoNumber +
|
|
37
|
-
requireMultiNumber +
|
|
38
|
-
writerequireLength +
|
|
39
|
-
reserve +
|
|
40
|
-
writeCommand +
|
|
41
|
-
writeSubCommand +
|
|
42
|
-
deviceCode +
|
|
43
|
-
writeStartDevice +
|
|
44
|
-
(writeLength || writeLengthDevice) +
|
|
45
|
-
writeCoilValue
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static getWriteWordCommand(deviceCode, writeStartDevice, writeWordValue) {
|
|
50
|
-
return (
|
|
51
|
-
subHeader +
|
|
52
|
-
networkNumber +
|
|
53
|
-
requireNumber +
|
|
54
|
-
requireIoNumber +
|
|
55
|
-
requireMultiNumber +
|
|
56
|
-
writewordrequireLength +
|
|
57
|
-
reserve +
|
|
58
|
-
writeCommand +
|
|
59
|
-
writeWordSubCommand +
|
|
60
|
-
deviceCode +
|
|
61
|
-
writeStartDevice +
|
|
62
|
-
writeLengthDevice +
|
|
63
|
-
writeWordValue
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static getReadCoilCommand(deviceCode, readStartDevice, readLength) {
|
|
68
|
-
if (readLength) {
|
|
69
|
-
readLength = readLength.toString().padStart(4, '0')
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
subHeader +
|
|
74
|
-
networkNumber +
|
|
75
|
-
requireNumber +
|
|
76
|
-
requireIoNumber +
|
|
77
|
-
requireMultiNumber +
|
|
78
|
-
readrequireLength +
|
|
79
|
-
reserve +
|
|
80
|
-
readCommand +
|
|
81
|
-
readCoilSubCommand +
|
|
82
|
-
deviceCode +
|
|
83
|
-
readStartDevice +
|
|
84
|
-
(readLength || readLengthDevice)
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
static getReadWordCommand(deviceCode, readStartDevice) {
|
|
89
|
-
return (
|
|
90
|
-
subHeader +
|
|
91
|
-
networkNumber +
|
|
92
|
-
requireNumber +
|
|
93
|
-
requireIoNumber +
|
|
94
|
-
requireMultiNumber +
|
|
95
|
-
readrequireLength +
|
|
96
|
-
reserve +
|
|
97
|
-
readCommand +
|
|
98
|
-
readWordSubCommand +
|
|
99
|
-
deviceCode +
|
|
100
|
-
readStartDevice +
|
|
101
|
-
readLengthDevice
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async ready(connectionConfigs) {
|
|
106
|
-
await Promise.all(connectionConfigs.map(this.connect))
|
|
107
|
-
|
|
108
|
-
ConnectionManager.logger.info('mitsubishi-plc connections are ready')
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async connect(config) {
|
|
112
|
-
if (ConnectionManager.getConnectionInstance(config)) {
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
var [host, port = 1025] = config.endpoint.split(':')
|
|
117
|
-
|
|
118
|
-
var socket = new PromiseSocket(new net.Socket())
|
|
119
|
-
|
|
120
|
-
await socket.connect(port, host)
|
|
121
|
-
|
|
122
|
-
var queue = new PQueue({ concurrency: 1 })
|
|
123
|
-
var keepalive = true
|
|
124
|
-
|
|
125
|
-
ConnectionManager.addConnectionInstance(config, {
|
|
126
|
-
request: async function (message, length, { logger }) {
|
|
127
|
-
return await queue.add(async () => {
|
|
128
|
-
while (keepalive) {
|
|
129
|
-
try {
|
|
130
|
-
/* send request message */
|
|
131
|
-
await socket.write(message)
|
|
132
|
-
logger && logger.info(`Request : ${message}`)
|
|
133
|
-
var responseCompleted = ''
|
|
134
|
-
|
|
135
|
-
if (length > 0) {
|
|
136
|
-
while (length - responseCompleted.length > 0) {
|
|
137
|
-
logger && logger.info(`Will read ${length - responseCompleted.length}`)
|
|
138
|
-
let response = await socket.read() // length - responseCompleted.length)
|
|
139
|
-
if (!response) {
|
|
140
|
-
// socket ended or closed
|
|
141
|
-
throw new Error('socket closed')
|
|
142
|
-
}
|
|
143
|
-
responseCompleted += response.toString()
|
|
144
|
-
}
|
|
145
|
-
} else {
|
|
146
|
-
let response = await socket.read()
|
|
147
|
-
if (!response) {
|
|
148
|
-
// socket ended or closed
|
|
149
|
-
throw new Error('socket closed')
|
|
150
|
-
}
|
|
151
|
-
responseCompleted = response.toString()
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
logger && logger.info(`Response : ${responseCompleted}`)
|
|
155
|
-
return responseCompleted
|
|
156
|
-
} catch (e) {
|
|
157
|
-
logger.error('plc command(write-read) failed.', e)
|
|
158
|
-
|
|
159
|
-
if (keepalive) {
|
|
160
|
-
socket && socket.destroy()
|
|
161
|
-
|
|
162
|
-
socket = new PromiseSocket(new net.Socket())
|
|
163
|
-
await socket.connect(port, host)
|
|
164
|
-
|
|
165
|
-
await sleep(1000)
|
|
166
|
-
} else {
|
|
167
|
-
throw e
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
throw new Error(`${config.name} maybe disconnected normally`)
|
|
173
|
-
})
|
|
174
|
-
},
|
|
175
|
-
close: function () {
|
|
176
|
-
queue.clear()
|
|
177
|
-
keepalive = false
|
|
178
|
-
socket.destroy()
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
ConnectionManager.logger.info(`mitsubishi-plc connection(${config.name}:${config.endpoint}) is connected`)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async disconnect(connection: Connection) {
|
|
186
|
-
var { close } = ConnectionManager.removeConnectionInstance(connection)
|
|
187
|
-
close()
|
|
188
|
-
|
|
189
|
-
ConnectionManager.logger.info(`mitsubishi-plc connection(${connection.name}) is disconnected`)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
get parameterSpec() {
|
|
193
|
-
return [
|
|
194
|
-
{
|
|
195
|
-
type: 'checkbox',
|
|
196
|
-
name: 'keepalive',
|
|
197
|
-
label: 'keepalive'
|
|
198
|
-
}
|
|
199
|
-
]
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
get taskPrefixes() {
|
|
203
|
-
return ['melsec']
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
get help() {
|
|
207
|
-
return 'integration/connector/melsec-plc'
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
ConnectionManager.registerConnector('melsec-plc', new MelsecPLCConnector())
|
package/server/engine/index.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { MelsecPLCConnector } from '../connector/melsec-plc'
|
|
3
|
-
|
|
4
|
-
async function MelsecReadCoil(step, { logger, domain }) {
|
|
5
|
-
var {
|
|
6
|
-
connection: connectionName,
|
|
7
|
-
params: { plcAddress: address, readLength: readLength }
|
|
8
|
-
} = step
|
|
9
|
-
|
|
10
|
-
var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
|
|
11
|
-
if (!connection) {
|
|
12
|
-
throw new Error(`connection '${connectionName}' is not established.`)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
var { request } = connection
|
|
16
|
-
|
|
17
|
-
var deviceCode = address.substring(0, 1) + '*'
|
|
18
|
-
var af_address = Number(address.substring(1)).toString()
|
|
19
|
-
var len = af_address.length
|
|
20
|
-
for (var i = 0; i < 6 - len; i++) {
|
|
21
|
-
af_address = '0' + af_address
|
|
22
|
-
}
|
|
23
|
-
var readStartDevice = af_address
|
|
24
|
-
var sendMessage = MelsecPLCConnector.getReadCoilCommand(deviceCode, readStartDevice, readLength)
|
|
25
|
-
|
|
26
|
-
// Request : 500000FF03FF000018000004010001M*0001000001
|
|
27
|
-
// Response : D00000FF03FF00000500000
|
|
28
|
-
var content = await request(sendMessage, 23, { logger }) // (22 + readLength)에서 현재 readLength는 1로 고정
|
|
29
|
-
|
|
30
|
-
// TODO readLength가 1이 아닐때 데이터 처리.
|
|
31
|
-
if (content.substring(17, 18) == '5') {
|
|
32
|
-
var data = content.substring(22, 23)
|
|
33
|
-
|
|
34
|
-
logger.info(content)
|
|
35
|
-
logger.info(`received response is ok. received: ${data}`)
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
data
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
// error
|
|
42
|
-
throw new Error('response not applicable')
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
MelsecReadCoil.parameterSpec = [
|
|
47
|
-
{
|
|
48
|
-
type: 'string',
|
|
49
|
-
name: 'plcAddress',
|
|
50
|
-
label: 'plc_address'
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
type: 'number',
|
|
54
|
-
name: 'readLength',
|
|
55
|
-
label: 'read_length'
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
|
|
59
|
-
MelsecReadCoil.help = 'integration/task/melsec-read-coil'
|
|
60
|
-
|
|
61
|
-
TaskRegistry.registerTaskHandler('melsec-read-coil', MelsecReadCoil)
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { MelsecPLCConnector } from '../connector/melsec-plc'
|
|
3
|
-
|
|
4
|
-
async function MelsecReadWord(step, { logger, domain }) {
|
|
5
|
-
var {
|
|
6
|
-
connection: connectionName,
|
|
7
|
-
params: { plcAddress: address, signed = false }
|
|
8
|
-
} = step
|
|
9
|
-
|
|
10
|
-
var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
|
|
11
|
-
if (!connection) {
|
|
12
|
-
throw new Error(`connection '${connectionName}' is not established.`)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
var { request } = connection
|
|
16
|
-
|
|
17
|
-
var deviceCode = address.substring(0, 1) + '*'
|
|
18
|
-
var af_address = Number(address.substring(1)).toString()
|
|
19
|
-
var len = af_address.length
|
|
20
|
-
for (var i = 0; i < 6 - len; i++) {
|
|
21
|
-
af_address = '0' + af_address
|
|
22
|
-
}
|
|
23
|
-
var readStartDevice = af_address
|
|
24
|
-
var sendMessage = MelsecPLCConnector.getReadWordCommand(deviceCode, readStartDevice)
|
|
25
|
-
|
|
26
|
-
// Request : 500000FF03FF000018000004010000D*0001010001
|
|
27
|
-
// Response : D00000FF03FF000008000003E9
|
|
28
|
-
var content = await request(sendMessage, 26, { logger })
|
|
29
|
-
|
|
30
|
-
var wordValue = content.substring(22, 26)
|
|
31
|
-
var data = parseInt(wordValue, 16)
|
|
32
|
-
|
|
33
|
-
if (signed && (data & 0x8000) > 0) {
|
|
34
|
-
data -= 0x10000
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
logger.info(content)
|
|
38
|
-
logger.info(`received response is ok. received: ${data}`)
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
data
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
MelsecReadWord.parameterSpec = [
|
|
46
|
-
{
|
|
47
|
-
type: 'string',
|
|
48
|
-
name: 'plcAddress',
|
|
49
|
-
label: 'plc_address'
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
type: 'checkbox',
|
|
53
|
-
name: 'signed',
|
|
54
|
-
label: 'signed'
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
|
|
58
|
-
MelsecReadWord.help = 'integration/task/melsec-read-word'
|
|
59
|
-
|
|
60
|
-
TaskRegistry.registerTaskHandler('melsec-read-word', MelsecReadWord)
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, Context, ScenarioInstanceStatus, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { sleep } from '@things-factory/utils'
|
|
3
|
-
|
|
4
|
-
import { MelsecPLCConnector } from '../connector/melsec-plc'
|
|
5
|
-
|
|
6
|
-
async function MelsecWaitForCoil(step, { logger, root, domain }: Context) {
|
|
7
|
-
var {
|
|
8
|
-
connection: connectionName,
|
|
9
|
-
params: { plcAddress: address, value, waitTerm = 50 }
|
|
10
|
-
} = step
|
|
11
|
-
|
|
12
|
-
var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
|
|
13
|
-
if (!connection) {
|
|
14
|
-
throw new Error(`connection '${connectionName}' is not established.`)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
var { request } = connection
|
|
18
|
-
|
|
19
|
-
var deviceCode = address.substring(0, 1) + '*'
|
|
20
|
-
var af_address = Number(address.substring(1)).toString()
|
|
21
|
-
var len = af_address.length
|
|
22
|
-
for (var i = 0; i < 6 - len; i++) {
|
|
23
|
-
af_address = '0' + af_address
|
|
24
|
-
}
|
|
25
|
-
var readStartDevice = af_address
|
|
26
|
-
var sendMessage = MelsecPLCConnector.getReadCoilCommand(deviceCode, readStartDevice, undefined)
|
|
27
|
-
|
|
28
|
-
while (true) {
|
|
29
|
-
let state = root.getState()
|
|
30
|
-
if (state == ScenarioInstanceStatus.STARTED /* STARTED */) {
|
|
31
|
-
var content = await request(sendMessage, 23, { logger })
|
|
32
|
-
|
|
33
|
-
if (content.substring(17, 18) == '5') {
|
|
34
|
-
var coilValue = content.substring(22, 23)
|
|
35
|
-
|
|
36
|
-
if (value == coilValue) {
|
|
37
|
-
logger.info('received response is ok. required: %s, received: %s', value, coilValue)
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
data: coilValue
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
logger.info('received response, but not accepted. required: %s, received: %s', value, coilValue)
|
|
44
|
-
await sleep(waitTerm)
|
|
45
|
-
continue
|
|
46
|
-
}
|
|
47
|
-
} else {
|
|
48
|
-
// error
|
|
49
|
-
throw new Error('response not applicable')
|
|
50
|
-
}
|
|
51
|
-
} else if (state == ScenarioInstanceStatus.STOPPED /* PAUSED */) {
|
|
52
|
-
await sleep(waitTerm)
|
|
53
|
-
} else {
|
|
54
|
-
throw new Error('scenario stopped unexpectedly')
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
MelsecWaitForCoil.parameterSpec = [
|
|
60
|
-
{
|
|
61
|
-
type: 'string',
|
|
62
|
-
name: 'plcAddress',
|
|
63
|
-
label: 'plc_address'
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
type: 'string',
|
|
67
|
-
name: 'value',
|
|
68
|
-
label: 'expected_value'
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: 'number',
|
|
72
|
-
name: 'waitTerm',
|
|
73
|
-
placeholder: 'milli-seconds',
|
|
74
|
-
label: 'wait_term'
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
MelsecWaitForCoil.help = 'integration/task/melsec-wait-coil'
|
|
79
|
-
|
|
80
|
-
TaskRegistry.registerTaskHandler('melsec-wait-coil', MelsecWaitForCoil)
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { MelsecPLCConnector } from '../connector/melsec-plc'
|
|
3
|
-
|
|
4
|
-
import { sleep } from '@things-factory/utils'
|
|
5
|
-
|
|
6
|
-
async function MelsecWriteCoil(step, { logger, domain }) {
|
|
7
|
-
var {
|
|
8
|
-
connection: connectionName,
|
|
9
|
-
params: { plcAddress: address, value, writeLength = 1, autoReset, delay = 50 }
|
|
10
|
-
} = step
|
|
11
|
-
|
|
12
|
-
var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
|
|
13
|
-
if (!connection) {
|
|
14
|
-
throw new Error(`connection '${connectionName}' is not established.`)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
var { request } = connection
|
|
18
|
-
|
|
19
|
-
var w_address = address
|
|
20
|
-
var w_value = value
|
|
21
|
-
var deviceCode = w_address.substring(0, 1) + '*'
|
|
22
|
-
|
|
23
|
-
var af_address = Number(w_address.substring(1)).toString()
|
|
24
|
-
var len = af_address.length
|
|
25
|
-
for (var i = 0; i < 6 - len; i++) {
|
|
26
|
-
af_address = '0' + af_address
|
|
27
|
-
}
|
|
28
|
-
var writeStartDevice = af_address
|
|
29
|
-
|
|
30
|
-
if (w_value == 1) {
|
|
31
|
-
var writeCoilValue = '1'
|
|
32
|
-
} else {
|
|
33
|
-
var writeCoilValue = '0'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
await doRequest(request, deviceCode, writeStartDevice, writeCoilValue, writeLength, logger)
|
|
37
|
-
|
|
38
|
-
if (autoReset) {
|
|
39
|
-
await sleep(delay)
|
|
40
|
-
|
|
41
|
-
await doRequest(request, deviceCode, writeStartDevice, Number(!Number(writeCoilValue)), writeLength, logger)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
data: writeCoilValue
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function doRequest(request, deviceCode, writeStartDevice, writeCoilValue, writeLength, logger) {
|
|
50
|
-
var sendMessage = MelsecPLCConnector.getWriteCoilCommand(deviceCode, writeStartDevice, writeCoilValue, writeLength)
|
|
51
|
-
// Request : 500000FF03FF000019000014010001M*00033300011
|
|
52
|
-
// Response : D00000FF03FF0000040000
|
|
53
|
-
var content = await request(sendMessage, 22, { logger })
|
|
54
|
-
|
|
55
|
-
// TODO writeLength 1이 아닐때 데이터 처리.
|
|
56
|
-
if (content.substring(17, 18) == '4') {
|
|
57
|
-
// ok
|
|
58
|
-
return {
|
|
59
|
-
data: writeCoilValue
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
// error
|
|
63
|
-
throw new Error('response not applicable')
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
MelsecWriteCoil.parameterSpec = [
|
|
68
|
-
{
|
|
69
|
-
type: 'string',
|
|
70
|
-
name: 'plcAddress',
|
|
71
|
-
placeholder: 'M0,Y1,..',
|
|
72
|
-
label: 'plc_address'
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
type: 'number',
|
|
76
|
-
name: 'writeLength',
|
|
77
|
-
label: 'write_length'
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: 'number',
|
|
81
|
-
name: 'value',
|
|
82
|
-
label: 'value'
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
type: 'checkbox',
|
|
86
|
-
name: 'autoReset',
|
|
87
|
-
label: 'auto_reset'
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
type: 'number',
|
|
91
|
-
name: 'delay',
|
|
92
|
-
placeholder: 'milisecodes, default is 50ms',
|
|
93
|
-
label: 'reset_delay'
|
|
94
|
-
}
|
|
95
|
-
]
|
|
96
|
-
|
|
97
|
-
MelsecWriteCoil.help = 'integration/task/melsec-write-coil'
|
|
98
|
-
|
|
99
|
-
TaskRegistry.registerTaskHandler('melsec-write-coil', MelsecWriteCoil)
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { access } from '@things-factory/utils'
|
|
3
|
-
import { MelsecPLCConnector } from '../connector/melsec-plc'
|
|
4
|
-
|
|
5
|
-
async function MelsecWriteWord(step, { data, logger, domain }) {
|
|
6
|
-
var {
|
|
7
|
-
connection: connectionName,
|
|
8
|
-
params: { plcAddress: address, accessor, value }
|
|
9
|
-
} = step
|
|
10
|
-
|
|
11
|
-
var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
|
|
12
|
-
if (!connection) {
|
|
13
|
-
throw new Error(`connection '${connectionName}' is not established.`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
var { request } = connection
|
|
17
|
-
|
|
18
|
-
var w_address = address
|
|
19
|
-
var deviceCode = w_address.substring(0, 1) + '*'
|
|
20
|
-
|
|
21
|
-
var af_address = Number(w_address.substring(1)).toString()
|
|
22
|
-
var len = af_address.length
|
|
23
|
-
for (var i = 0; i < 6 - len; i++) {
|
|
24
|
-
af_address = '0' + af_address
|
|
25
|
-
}
|
|
26
|
-
var writeStartDevice = af_address
|
|
27
|
-
|
|
28
|
-
value = accessor ? access(accessor, data) : value
|
|
29
|
-
if (isNaN(value)) {
|
|
30
|
-
throw new Error(`invalid number value : ${value}`)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
var valueDefine = Number(value).toString(16)
|
|
34
|
-
var writeWordValue = ''
|
|
35
|
-
|
|
36
|
-
if (valueDefine.length == 1) {
|
|
37
|
-
writeWordValue = '000' + Number(value).toString(16)
|
|
38
|
-
} else if (valueDefine.length == 2) {
|
|
39
|
-
writeWordValue = '00' + Number(value).toString(16)
|
|
40
|
-
} else if (valueDefine.length == 3) {
|
|
41
|
-
writeWordValue = '0' + Number(value).toString(16)
|
|
42
|
-
} else if (valueDefine.length == 4) {
|
|
43
|
-
writeWordValue = Number(value).toString(16)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Request : 500000FF03FF00001C000014010000D*00010000010001
|
|
47
|
-
// Response : D00000FF03FF0000040000
|
|
48
|
-
logger.info(`will send request value: ${value}:${writeWordValue}`)
|
|
49
|
-
|
|
50
|
-
var sendMessage = MelsecPLCConnector.getWriteWordCommand(deviceCode, writeStartDevice, writeWordValue)
|
|
51
|
-
var content = await request(sendMessage, 22, { logger })
|
|
52
|
-
|
|
53
|
-
logger.info(`received response: ${content}`)
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
data: writeWordValue
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
MelsecWriteWord.parameterSpec = [
|
|
61
|
-
{
|
|
62
|
-
type: 'string',
|
|
63
|
-
name: 'plcAddress',
|
|
64
|
-
placeholder: 'M0,Y1,..',
|
|
65
|
-
label: 'plc_address'
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
type: 'scenario-step-input',
|
|
69
|
-
name: 'accessor',
|
|
70
|
-
label: 'accessor'
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
type: 'number',
|
|
74
|
-
name: 'value',
|
|
75
|
-
label: 'value'
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
MelsecWriteWord.help = 'integration/task/melsec-write-word'
|
|
80
|
-
|
|
81
|
-
TaskRegistry.registerTaskHandler('melsec-write-word', MelsecWriteWord)
|
package/server/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './engine'
|