node-opcua-file-transfer 2.51.0
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/.mocharc.yml +11 -0
- package/LICENSE +20 -0
- package/dist/client/client_file.d.ts +68 -0
- package/dist/client/client_file.js +310 -0
- package/dist/client/client_file.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/open_mode.d.ts +39 -0
- package/dist/open_mode.js +45 -0
- package/dist/open_mode.js.map +1 -0
- package/dist/server/file_type_helpers.d.ts +68 -0
- package/dist/server/file_type_helpers.js +493 -0
- package/dist/server/file_type_helpers.js.map +1 -0
- package/package.json +58 -0
- package/readme.md +204 -0
- package/source/client/client_file.ts +322 -0
- package/source/index.ts +5 -0
- package/source/open_mode.ts +41 -0
- package/source/server/file_type_helpers.ts +643 -0
package/readme.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
## introduction
|
|
2
|
+
|
|
3
|
+
this package provides an implementation of the OPCUA File Transfer
|
|
4
|
+
specification as per OPCUA 1.0.4 part 5 Annex C (page 99)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
$ npm install node-opcua
|
|
11
|
+
$ npm install node-opcua-file-transfer
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## exposing a File node in the addressSpace
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
import { OPCUAServer, UAFileType } from "node-opcua";
|
|
18
|
+
import { installFileType } from "node-opcua-file-transfer";
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
|
|
24
|
+
const server = new OPCUAServer({
|
|
25
|
+
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
await server.initialize();
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
// let say we want to create a access to this file:
|
|
32
|
+
const my_data_filename = "/data/someFile.txt";
|
|
33
|
+
await promisify(fs.writeFile)(my_data_filename, "some content", "utf8");
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// now add a file object in the address Space
|
|
37
|
+
const addressSpace = server.engine.addressSpace;
|
|
38
|
+
|
|
39
|
+
// retrieve the FileType UAObjectType
|
|
40
|
+
const fileType = addressSpace.findObjectType("FileType")!;
|
|
41
|
+
|
|
42
|
+
// create a instance of FileType
|
|
43
|
+
const myFile = fileType.instantiate({
|
|
44
|
+
nodeId: "s=MyFile",
|
|
45
|
+
browseName: "MyFile",
|
|
46
|
+
organizedBy: addressSpace.rootFolder.objects
|
|
47
|
+
}) as UAFileType;
|
|
48
|
+
|
|
49
|
+
// now bind the opcuaFile object with our file
|
|
50
|
+
installFileType(opcuaFile, {
|
|
51
|
+
filename: my_data_filename
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
## accessing a File node from a node-opcua client : ClientFile
|
|
58
|
+
|
|
59
|
+
We assume that we have a valid OPCUA Client Session
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
import { OPCUAClient } from "node-opcua";
|
|
63
|
+
import { ClientFile } from "node-opcua-file-transfer";
|
|
64
|
+
|
|
65
|
+
const client = OPCUAClient.create({});
|
|
66
|
+
|
|
67
|
+
await client.connect();
|
|
68
|
+
const session = await client.createSession();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Let's assume that the nodeId of the file object is "ns=1;s=MyFile"
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
import {ClientFile,OpenFileMode } from "node-opcua-file-transfer";
|
|
75
|
+
|
|
76
|
+
//
|
|
77
|
+
const fileNodeId = "ns=1;s=MyFile";
|
|
78
|
+
|
|
79
|
+
// let's create a client file object from the session and nodeId
|
|
80
|
+
const clientFile = new ClientFile(session, fileNodeId);
|
|
81
|
+
|
|
82
|
+
// let's open the file
|
|
83
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
84
|
+
await clientFile.open(mode);
|
|
85
|
+
|
|
86
|
+
// ... do some reading or writing
|
|
87
|
+
|
|
88
|
+
// don't forget to close the file when done
|
|
89
|
+
await clientFile.close();
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### operations
|
|
93
|
+
|
|
94
|
+
#### ClientFile#size(): Promise<UInt64> : get file size
|
|
95
|
+
|
|
96
|
+
You can read the size of the file at any time.
|
|
97
|
+
``` javascript
|
|
98
|
+
const clientFile = new ClientFile(session, fileNodeId);
|
|
99
|
+
|
|
100
|
+
const size = await clientFile.size();
|
|
101
|
+
console.log("the current file size is : ",size," bytes);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### ClientFile#open(mode: OpenFileMode) : open a file
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
108
|
+
await clientFile.open(mode);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### OpenFileMode enumeration
|
|
112
|
+
|
|
113
|
+
| Mode | Description |
|
|
114
|
+
|------|-------------|
|
|
115
|
+
| Read |The file is opened for reading. the Write method cannot be executed. |
|
|
116
|
+
| Write|The file is opened for writing. the Read cannot be executed. |
|
|
117
|
+
| ReadWrite| The file is opened for reading an writing |
|
|
118
|
+
| WriteEraseExisting | File is opened for writing only. The existing content of the file is erased and an empty file is provided. |
|
|
119
|
+
| ReadWriteEraseExisting | File is opened for reading and writing. The existing content of the file is erased and an empty file is provided.|
|
|
120
|
+
| WriteAppend | File is opened for writing only and position is set at the end of the file |
|
|
121
|
+
| ReadWriteAppend | File is opened for reading and writing and position is set at the end of the file |
|
|
122
|
+
}
|
|
123
|
+
#### ClientFile#close() : close a file
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
127
|
+
await clientFile.open(mode);
|
|
128
|
+
|
|
129
|
+
// ... do some reading or writing
|
|
130
|
+
|
|
131
|
+
// don't forget to close the file when done
|
|
132
|
+
await clientFile.close();
|
|
133
|
+
```
|
|
134
|
+
#### ClientFile#setPosition(pos: UInt64) : Setting read/write position
|
|
135
|
+
|
|
136
|
+
Once the file is opened, the position for reading or writing can be set
|
|
137
|
+
using setPosition.
|
|
138
|
+
* setPosition expect a UInt64 parameter (see note below)
|
|
139
|
+
* setPosition will throw an exception if file is not opened
|
|
140
|
+
|
|
141
|
+
``` javascript
|
|
142
|
+
const clientFile = new ClientFile(session, fileNodeId);
|
|
143
|
+
|
|
144
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
145
|
+
await clientFile.open(mode);
|
|
146
|
+
|
|
147
|
+
await client.setPosition([0,32]);
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### ClientFile#getPosition(): Promise<UInt64> Getting read/write position
|
|
152
|
+
Once the file is opened, the position for reading or writing can be retrieved
|
|
153
|
+
using getPosition.
|
|
154
|
+
* getPosition returns a UInt64 parameter (see note below)
|
|
155
|
+
* getPosition will throw an exception if file is not opened
|
|
156
|
+
|
|
157
|
+
``` javascript
|
|
158
|
+
const clientFile = new ClientFile(session, fileNodeId);
|
|
159
|
+
|
|
160
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
161
|
+
await clientFile.open(mode);
|
|
162
|
+
|
|
163
|
+
await client.setPosition(32);
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### ClientFile#write(buf: Buffer) : Writing data to the file
|
|
168
|
+
|
|
169
|
+
Data can be writing to the file at the current cursor position.
|
|
170
|
+
Data must be passed in a buffer.
|
|
171
|
+
* write will throw an exception if file is not opened
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const dataToWrite = Buffer.from("Some data");
|
|
175
|
+
|
|
176
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
177
|
+
await clientFile.open(mode);
|
|
178
|
+
await clientFile.write(dataToWrite);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
#### ClientFile#read(): Promise<Buffer> :reading data to the file
|
|
183
|
+
|
|
184
|
+
Data can be writing to the file at the current cursor position.
|
|
185
|
+
Data must be passed in a buffer.
|
|
186
|
+
* read will throw an exception if file is not opened
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
|
|
190
|
+
const mode = OpenFileMode.ReadWriteAppend;
|
|
191
|
+
await clientFile.open(mode);
|
|
192
|
+
|
|
193
|
+
// read 200 bytes from position 32
|
|
194
|
+
await clientFile.setPosition([0,32]);
|
|
195
|
+
const data: Buffer = await clientFile.read(200);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### notes
|
|
199
|
+
|
|
200
|
+
UInt64
|
|
201
|
+
* At this time BigInt, is not supported by all version of nodeJs that are targeted by node-opcua.
|
|
202
|
+
UInt64 values are currently stored into a array of 2 32bits numbers : [ High,Low]
|
|
203
|
+
|
|
204
|
+
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opcua-file-transfer
|
|
3
|
+
*/
|
|
4
|
+
import { Byte, Int32, UInt16, UInt32, UInt64 } from "node-opcua-basic-types";
|
|
5
|
+
import { AttributeIds } from "node-opcua-data-model";
|
|
6
|
+
import { NodeId, resolveNodeId } from "node-opcua-nodeid";
|
|
7
|
+
import { IBasicSession } from "node-opcua-pseudo-session";
|
|
8
|
+
import { ReadValueIdOptions } from "node-opcua-service-read";
|
|
9
|
+
import { BrowsePath, makeBrowsePath } from "node-opcua-service-translate-browse-path";
|
|
10
|
+
import { StatusCodes } from "node-opcua-status-code";
|
|
11
|
+
import { DataType, VariantArrayType } from "node-opcua-variant";
|
|
12
|
+
import { MethodIds } from "node-opcua-constants";
|
|
13
|
+
|
|
14
|
+
import { checkDebugFlag, make_debugLog, make_errorLog } from "node-opcua-debug";
|
|
15
|
+
|
|
16
|
+
const debugLog = make_debugLog("FileType");
|
|
17
|
+
const errorLog = make_errorLog("FileType");
|
|
18
|
+
const doDebug = checkDebugFlag("FileType");
|
|
19
|
+
|
|
20
|
+
import { OpenFileMode } from "../open_mode";
|
|
21
|
+
export { OpenFileMode } from "../open_mode";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
export class ClientFile {
|
|
28
|
+
|
|
29
|
+
public static useGlobalMethod = false;
|
|
30
|
+
|
|
31
|
+
public fileHandle = 0;
|
|
32
|
+
protected session: IBasicSession;
|
|
33
|
+
protected readonly fileNodeId: NodeId;
|
|
34
|
+
|
|
35
|
+
private openMethodNodeId?: NodeId;
|
|
36
|
+
private closeMethodNodeId?: NodeId;
|
|
37
|
+
private setPositionNodeId?: NodeId;
|
|
38
|
+
private getPositionNodeId?: NodeId;
|
|
39
|
+
private readNodeId?: NodeId;
|
|
40
|
+
private writeNodeId?: NodeId;
|
|
41
|
+
private openCountNodeId?: NodeId;
|
|
42
|
+
private sizeNodeId?: NodeId;
|
|
43
|
+
|
|
44
|
+
constructor(session: IBasicSession, nodeId: NodeId) {
|
|
45
|
+
this.session = session;
|
|
46
|
+
this.fileNodeId = nodeId;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public async open(mode: OpenFileMode): Promise<number> {
|
|
50
|
+
|
|
51
|
+
if (mode === null || mode === undefined) {
|
|
52
|
+
throw new Error("expecting a validMode " + OpenFileMode[mode]);
|
|
53
|
+
}
|
|
54
|
+
if (this.fileHandle) {
|
|
55
|
+
throw new Error("File has already be opened");
|
|
56
|
+
}
|
|
57
|
+
await this.ensureInitialized();
|
|
58
|
+
|
|
59
|
+
const result = await this.session.call({
|
|
60
|
+
inputArguments: [
|
|
61
|
+
{ dataType: DataType.Byte, value: mode as Byte }
|
|
62
|
+
],
|
|
63
|
+
methodId: this.openMethodNodeId,
|
|
64
|
+
objectId: this.fileNodeId
|
|
65
|
+
});
|
|
66
|
+
if (result.statusCode !== StatusCodes.Good) {
|
|
67
|
+
debugLog("Cannot open file : ");
|
|
68
|
+
throw new Error("cannot open file statusCode = " + result.statusCode.toString() + " mode = " + OpenFileMode[mode]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.fileHandle = result.outputArguments![0].value;
|
|
72
|
+
|
|
73
|
+
return this.fileHandle;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public async close(): Promise<void> {
|
|
77
|
+
if (!this.fileHandle) {
|
|
78
|
+
throw new Error("File has not been opened yet");
|
|
79
|
+
}
|
|
80
|
+
await this.ensureInitialized();
|
|
81
|
+
|
|
82
|
+
const result = await this.session.call({
|
|
83
|
+
inputArguments: [
|
|
84
|
+
{ dataType: DataType.UInt32, value: this.fileHandle }
|
|
85
|
+
],
|
|
86
|
+
methodId: this.closeMethodNodeId,
|
|
87
|
+
objectId: this.fileNodeId
|
|
88
|
+
});
|
|
89
|
+
if (result.statusCode !== StatusCodes.Good) {
|
|
90
|
+
debugLog("Cannot close file : ");
|
|
91
|
+
throw new Error("cannot close file statusCode = " + result.statusCode.toString());
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.fileHandle = 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public async getPosition(): Promise<UInt64> {
|
|
98
|
+
await this.ensureInitialized();
|
|
99
|
+
if (!this.fileHandle) {
|
|
100
|
+
throw new Error("File has not been opened yet");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const result = await this.session.call({
|
|
104
|
+
inputArguments: [
|
|
105
|
+
{ dataType: DataType.UInt32, value: this.fileHandle }
|
|
106
|
+
],
|
|
107
|
+
methodId: this.getPositionNodeId,
|
|
108
|
+
objectId: this.fileNodeId
|
|
109
|
+
});
|
|
110
|
+
if (result.statusCode !== StatusCodes.Good) {
|
|
111
|
+
throw new Error("Error " + result.statusCode.toString());
|
|
112
|
+
}
|
|
113
|
+
return result.outputArguments![0].value as UInt64;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public async setPosition(position: UInt64 | UInt32): Promise<void> {
|
|
117
|
+
await this.ensureInitialized();
|
|
118
|
+
if (!this.fileHandle) {
|
|
119
|
+
throw new Error("File has not been opened yet");
|
|
120
|
+
}
|
|
121
|
+
if (typeof position === "number") {
|
|
122
|
+
position = [0, position];
|
|
123
|
+
}
|
|
124
|
+
const result = await this.session.call({
|
|
125
|
+
inputArguments: [
|
|
126
|
+
{ dataType: DataType.UInt32, value: this.fileHandle },
|
|
127
|
+
{
|
|
128
|
+
arrayType: VariantArrayType.Scalar,
|
|
129
|
+
dataType: DataType.UInt64,
|
|
130
|
+
value: position
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
methodId: this.setPositionNodeId,
|
|
134
|
+
objectId: this.fileNodeId
|
|
135
|
+
});
|
|
136
|
+
if (result.statusCode !== StatusCodes.Good) {
|
|
137
|
+
throw new Error("Error " + result.statusCode.toString());
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public async read(bytesToRead: Int32): Promise<Buffer> {
|
|
143
|
+
await this.ensureInitialized();
|
|
144
|
+
if (!this.fileHandle) {
|
|
145
|
+
throw new Error("File has not been opened yet");
|
|
146
|
+
}
|
|
147
|
+
const result = await this.session.call({
|
|
148
|
+
inputArguments: [
|
|
149
|
+
{ dataType: DataType.UInt32, value: this.fileHandle },
|
|
150
|
+
{
|
|
151
|
+
arrayType: VariantArrayType.Scalar,
|
|
152
|
+
dataType: DataType.Int32,
|
|
153
|
+
value: bytesToRead
|
|
154
|
+
}
|
|
155
|
+
],
|
|
156
|
+
methodId: this.readNodeId,
|
|
157
|
+
objectId: this.fileNodeId
|
|
158
|
+
});
|
|
159
|
+
if (result.statusCode !== StatusCodes.Good) {
|
|
160
|
+
throw new Error("Error " + result.statusCode.toString());
|
|
161
|
+
}
|
|
162
|
+
if (!result.outputArguments || result.outputArguments[0].dataType !== DataType.ByteString) {
|
|
163
|
+
throw new Error("Error invalid output");
|
|
164
|
+
}
|
|
165
|
+
return result.outputArguments![0].value as Buffer;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public async write(data: Buffer): Promise<void> {
|
|
169
|
+
await this.ensureInitialized();
|
|
170
|
+
if (!this.fileHandle) {
|
|
171
|
+
throw new Error("File has not been opened yet");
|
|
172
|
+
}
|
|
173
|
+
const result = await this.session.call({
|
|
174
|
+
inputArguments: [
|
|
175
|
+
{ dataType: DataType.UInt32, value: this.fileHandle },
|
|
176
|
+
{
|
|
177
|
+
arrayType: VariantArrayType.Scalar,
|
|
178
|
+
dataType: DataType.ByteString,
|
|
179
|
+
value: data
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
methodId: this.writeNodeId,
|
|
183
|
+
objectId: this.fileNodeId
|
|
184
|
+
});
|
|
185
|
+
if (result.statusCode !== StatusCodes.Good) {
|
|
186
|
+
throw new Error("Error " + result.statusCode.toString());
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public async openCount(): Promise<UInt16> {
|
|
192
|
+
await this.ensureInitialized();
|
|
193
|
+
const nodeToRead: ReadValueIdOptions = { nodeId: this.openCountNodeId!, attributeId: AttributeIds.Value };
|
|
194
|
+
const dataValue = await this.session.read(nodeToRead);
|
|
195
|
+
|
|
196
|
+
if (doDebug) {
|
|
197
|
+
debugLog(" OpenCount ", nodeToRead.nodeId!.toString(), dataValue.toString());
|
|
198
|
+
}
|
|
199
|
+
return dataValue.value.value;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public async size(): Promise<UInt64> {
|
|
203
|
+
await this.ensureInitialized();
|
|
204
|
+
const nodeToRead = { nodeId: this.sizeNodeId, attributeId: AttributeIds.Value };
|
|
205
|
+
const dataValue = await this.session.read(nodeToRead);
|
|
206
|
+
return dataValue.value.value;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// eslint-disable-next-line max-statements
|
|
210
|
+
protected async extractMethodsIds(): Promise<void> {
|
|
211
|
+
|
|
212
|
+
if (ClientFile.useGlobalMethod) {
|
|
213
|
+
debugLog("Using GlobalMethodId");
|
|
214
|
+
this.openMethodNodeId = resolveNodeId(MethodIds.FileType_Open);
|
|
215
|
+
this.closeMethodNodeId = resolveNodeId(MethodIds.FileType_Close);
|
|
216
|
+
this.setPositionNodeId = resolveNodeId(MethodIds.FileType_SetPosition);
|
|
217
|
+
this.getPositionNodeId = resolveNodeId(MethodIds.FileType_GetPosition);
|
|
218
|
+
this.writeNodeId = resolveNodeId(MethodIds.FileType_Write);
|
|
219
|
+
this.readNodeId = resolveNodeId(MethodIds.FileType_Read);
|
|
220
|
+
const browsePaths: BrowsePath[] = [
|
|
221
|
+
makeBrowsePath(this.fileNodeId, "/OpenCount"),
|
|
222
|
+
makeBrowsePath(this.fileNodeId, "/Size")
|
|
223
|
+
];
|
|
224
|
+
const results = await this.session.translateBrowsePath(browsePaths);
|
|
225
|
+
if (results[0].statusCode !== StatusCodes.Good) {
|
|
226
|
+
throw new Error("fileType object does not expose mandatory OpenCount Property");
|
|
227
|
+
}
|
|
228
|
+
if (results[1].statusCode !== StatusCodes.Good) {
|
|
229
|
+
throw new Error("fileType object does not expose mandatory Size Property");
|
|
230
|
+
}
|
|
231
|
+
this.openCountNodeId = results[0].targets![0].targetId;
|
|
232
|
+
this.sizeNodeId = results[1].targets![0].targetId;
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const browsePaths: BrowsePath[] = [
|
|
236
|
+
makeBrowsePath(this.fileNodeId, "/Open"),
|
|
237
|
+
makeBrowsePath(this.fileNodeId, "/Close"),
|
|
238
|
+
makeBrowsePath(this.fileNodeId, "/SetPosition"),
|
|
239
|
+
makeBrowsePath(this.fileNodeId, "/GetPosition"),
|
|
240
|
+
makeBrowsePath(this.fileNodeId, "/Write"),
|
|
241
|
+
makeBrowsePath(this.fileNodeId, "/Read"),
|
|
242
|
+
makeBrowsePath(this.fileNodeId, "/OpenCount"),
|
|
243
|
+
makeBrowsePath(this.fileNodeId, "/Size")
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
const results = await this.session.translateBrowsePath(browsePaths);
|
|
247
|
+
|
|
248
|
+
if (results[0].statusCode !== StatusCodes.Good) {
|
|
249
|
+
throw new Error("fileType object does not expose mandatory Open Method");
|
|
250
|
+
}
|
|
251
|
+
if (results[1].statusCode !== StatusCodes.Good) {
|
|
252
|
+
throw new Error("fileType object does not expose mandatory Close Method");
|
|
253
|
+
}
|
|
254
|
+
if (results[2].statusCode !== StatusCodes.Good) {
|
|
255
|
+
throw new Error("fileType object does not expose mandatory SetPosition Method");
|
|
256
|
+
}
|
|
257
|
+
if (results[3].statusCode !== StatusCodes.Good) {
|
|
258
|
+
throw new Error("fileType object does not expose mandatory GetPosition Method");
|
|
259
|
+
}
|
|
260
|
+
if (results[4].statusCode !== StatusCodes.Good) {
|
|
261
|
+
throw new Error("fileType object does not expose mandatory Write Method");
|
|
262
|
+
}
|
|
263
|
+
if (results[5].statusCode !== StatusCodes.Good) {
|
|
264
|
+
throw new Error("fileType object does not expose mandatory Read Method");
|
|
265
|
+
}
|
|
266
|
+
if (results[6].statusCode !== StatusCodes.Good) {
|
|
267
|
+
throw new Error("fileType object does not expose mandatory OpenCount Variable");
|
|
268
|
+
}
|
|
269
|
+
if (results[7].statusCode !== StatusCodes.Good) {
|
|
270
|
+
throw new Error("fileType object does not expose mandatory Size Variable");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (false && doDebug) {
|
|
274
|
+
results.map((x: any) => debugLog(x.toString()));
|
|
275
|
+
}
|
|
276
|
+
this.openMethodNodeId = results[0].targets![0].targetId;
|
|
277
|
+
this.closeMethodNodeId = results[1].targets![0].targetId;
|
|
278
|
+
this.setPositionNodeId = results[2].targets![0].targetId;
|
|
279
|
+
this.getPositionNodeId = results[3].targets![0].targetId;
|
|
280
|
+
this.writeNodeId = results[4].targets![0].targetId;
|
|
281
|
+
this.readNodeId = results[5].targets![0].targetId;
|
|
282
|
+
this.openCountNodeId = results[6].targets![0].targetId;
|
|
283
|
+
this.sizeNodeId = results[7].targets![0].targetId;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
protected async ensureInitialized(): Promise<void> {
|
|
287
|
+
if (!this.openMethodNodeId) {
|
|
288
|
+
await this.extractMethodsIds();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* 5.2.10 UserRolePermissions
|
|
295
|
+
*
|
|
296
|
+
* The optional UserRolePermissions Attribute specifies the Permissions that apply to a Node for
|
|
297
|
+
* all Roles granted to current Session. The value of the Attribute is an array of
|
|
298
|
+
* RolePermissionType Structures (see Table 8).
|
|
299
|
+
* Clients may determine their effective Permissions by logically ORing the Permissions for each
|
|
300
|
+
* Role in the array.
|
|
301
|
+
* The value of this Attribute is derived from the rules used by the Server to map Sessions to
|
|
302
|
+
* Roles. This mapping may be vendor specific or it may use the standard Role model defined in 4.8.
|
|
303
|
+
* This Attribute shall not be writeable.
|
|
304
|
+
* If not specified, the value of DefaultUserRolePermissions Property from the Namespace
|
|
305
|
+
* Metadata Object associated with the Node is used instead. If the NamespaceMetadata Object
|
|
306
|
+
* does not define the Property or does not exist, then the Server does not publish any information
|
|
307
|
+
* about Roles mapped to the current Session.
|
|
308
|
+
*
|
|
309
|
+
*
|
|
310
|
+
* 5.2.11 AccessRestrictions
|
|
311
|
+
* The optional AccessRestrictions Attribute specifies the AccessRestrictions that apply to a Node.
|
|
312
|
+
* Its data type is defined in 8.56. If a Server supports AccessRestrictions for a particular
|
|
313
|
+
* Namespace it adds the DefaultAccessRestrictions Property to the NamespaceMetadata Object
|
|
314
|
+
* for that Namespace (see Figure 8). If a particular Node in the Namespace needs to override
|
|
315
|
+
* the default value the Server adds the AccessRestrictions Attribute to the Node.
|
|
316
|
+
* If a Server implements a vendor specific access restriction model for a Namespace, it does not
|
|
317
|
+
* add the DefaultAccessRestrictions Property to the NamespaceMetadata Object.
|
|
318
|
+
*
|
|
319
|
+
*
|
|
320
|
+
* DefaultAccessRestrictions
|
|
321
|
+
*
|
|
322
|
+
*/
|
package/source/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opcua-file-transfer-server
|
|
3
|
+
*/
|
|
4
|
+
export enum OpenFileModeMask {
|
|
5
|
+
ReadBit = 0x01,
|
|
6
|
+
WriteBit = 0x02,
|
|
7
|
+
EraseExistingBit = 0x04,
|
|
8
|
+
AppendBit = 0x08,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export enum OpenFileMode {
|
|
12
|
+
/**
|
|
13
|
+
* Read bit 0 The file is opened for reading. If this bit is not
|
|
14
|
+
* set the Read Method cannot be executed.
|
|
15
|
+
*/
|
|
16
|
+
Read = OpenFileModeMask.ReadBit,
|
|
17
|
+
/**
|
|
18
|
+
* Write bit 1 The file is opened for writing. If this bit is not
|
|
19
|
+
* set the Write Method cannot be executed.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
Write = OpenFileModeMask.WriteBit,
|
|
23
|
+
ReadWrite = OpenFileModeMask.ReadBit + OpenFileModeMask.WriteBit,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* WriteEraseExisting
|
|
28
|
+
* EraseExisting 2 This bit can only be set if the file is opened for writing
|
|
29
|
+
* (Write bit is set). The existing content of the file is
|
|
30
|
+
* erased and an empty file is provided.
|
|
31
|
+
*/
|
|
32
|
+
WriteEraseExisting = OpenFileModeMask.EraseExistingBit + OpenFileModeMask.WriteBit,
|
|
33
|
+
ReadWriteEraseExisting = OpenFileModeMask.EraseExistingBit + OpenFileModeMask.WriteBit + OpenFileModeMask.ReadBit,
|
|
34
|
+
/**
|
|
35
|
+
* Append 3 When the Append bit is set the file is opened at end
|
|
36
|
+
* of the file, otherwise at begin of the file.
|
|
37
|
+
* The SetPosition Method can be used to change the position.
|
|
38
|
+
*/
|
|
39
|
+
WriteAppend = OpenFileModeMask.AppendBit + OpenFileModeMask.WriteBit,
|
|
40
|
+
ReadWriteAppend = OpenFileModeMask.AppendBit + OpenFileModeMask.WriteBit + OpenFileModeMask.ReadBit,
|
|
41
|
+
}
|