opcua 0.6 → 0.7
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.
- checksums.yaml +4 -4
- data/cert/cert.h +70 -0
- data/cert/cert_key.h +103 -0
- data/example/client.rb +2 -1
- data/example/server.rb +3 -1
- data/ext/opcua/client/client.c +388 -0
- data/ext/opcua/client/client.h +23 -0
- data/ext/opcua/server/server.c +392 -0
- data/ext/opcua/server/server.h +14 -0
- data/lib/opcua/client.rb +6 -1
- data/lib/opcua/server.rb +5 -1
- data/opcua.gemspec +3 -3
- metadata +13 -3
- data/lib/opcua/client.so +0 -0
- data/lib/opcua/server.so +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9386b3d4c28890fbc2d650b385caaae4c334acfadc5a60731e9c33cd0c78bed6
|
|
4
|
+
data.tar.gz: 05a1d8cb7504424fbba81ac9254fc49d2897bbde65170b3db6d25e1bc57010c5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48759b29e6c4b67bd730b57c8d1088251a5e96cfdd4f171955aca93521e0939955f88bbe76152008423457f5fb5fe0cf34e1e845822ceaee37fa4730dbaf85a4
|
|
7
|
+
data.tar.gz: 297417d2c1efd3430087c3c15436f69805364d56484ce42ffd3eaac9f8071006a7dc36df78e2682e20d92ec232be0b9a26f9d1d5da357af1339b4cf96bec722a
|
data/cert/cert.h
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
unsigned char cert_der[] = {
|
|
2
|
+
0x30, 0x82, 0x03, 0x18, 0x30, 0x82, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x01,
|
|
3
|
+
0x02, 0x02, 0x14, 0x39, 0x4d, 0x8d, 0x5f, 0xd4, 0xfe, 0x9d, 0x97, 0xef,
|
|
4
|
+
0xaa, 0x36, 0xc0, 0x7f, 0x64, 0x96, 0xfa, 0x3e, 0x4c, 0x8e, 0x33, 0x30,
|
|
5
|
+
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
|
|
6
|
+
0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
|
|
7
|
+
0x03, 0x0c, 0x0a, 0x72, 0x75, 0x62, 0x79, 0x2d, 0x6f, 0x70, 0x63, 0x75,
|
|
8
|
+
0x61, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x34, 0x32, 0x37, 0x31,
|
|
9
|
+
0x32, 0x34, 0x38, 0x34, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x34,
|
|
10
|
+
0x31, 0x36, 0x31, 0x32, 0x34, 0x38, 0x34, 0x38, 0x5a, 0x30, 0x15, 0x31,
|
|
11
|
+
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x72, 0x75,
|
|
12
|
+
0x62, 0x79, 0x2d, 0x6f, 0x70, 0x63, 0x75, 0x61, 0x30, 0x82, 0x01, 0x22,
|
|
13
|
+
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
|
|
14
|
+
0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
|
|
15
|
+
0x02, 0x82, 0x01, 0x01, 0x00, 0xf5, 0x91, 0xb2, 0x9b, 0x5a, 0x5a, 0x7f,
|
|
16
|
+
0xac, 0xc1, 0xfd, 0x5f, 0x2e, 0xc1, 0x6c, 0x2b, 0x89, 0x84, 0x04, 0x0f,
|
|
17
|
+
0xae, 0x4c, 0xc2, 0x26, 0x86, 0xc8, 0x45, 0xcd, 0x71, 0x1c, 0xa2, 0x30,
|
|
18
|
+
0x54, 0xcb, 0x40, 0xeb, 0x30, 0xdf, 0xbb, 0x6a, 0x4e, 0x95, 0x1d, 0x57,
|
|
19
|
+
0xeb, 0xed, 0xa0, 0x30, 0xe1, 0x8f, 0x9d, 0x0b, 0xb0, 0x55, 0x18, 0x98,
|
|
20
|
+
0xef, 0xd6, 0x36, 0xa5, 0xe5, 0x4c, 0x88, 0xa1, 0xb7, 0x29, 0x08, 0xec,
|
|
21
|
+
0xa3, 0x7b, 0xac, 0x30, 0x20, 0x9a, 0xd2, 0x5a, 0x2d, 0x2f, 0x22, 0x08,
|
|
22
|
+
0x1b, 0x94, 0x97, 0x4d, 0xdf, 0xc1, 0x1d, 0x20, 0xb3, 0x9b, 0x9e, 0x7b,
|
|
23
|
+
0x58, 0xb3, 0xf0, 0xe8, 0x29, 0x25, 0x41, 0xf5, 0x54, 0x50, 0xde, 0x83,
|
|
24
|
+
0xef, 0x31, 0xae, 0xae, 0xb7, 0xbd, 0x0a, 0xbb, 0x19, 0x35, 0xc2, 0x6b,
|
|
25
|
+
0x3b, 0xe5, 0x36, 0x24, 0xf2, 0xf9, 0xe9, 0xe6, 0xa2, 0xe7, 0xe2, 0x50,
|
|
26
|
+
0xfe, 0x19, 0xbd, 0x9f, 0x51, 0xbd, 0x0f, 0xfe, 0x2c, 0xf5, 0x91, 0x5a,
|
|
27
|
+
0x5a, 0xe1, 0x53, 0xe2, 0x44, 0x4d, 0x31, 0x5c, 0x80, 0xbd, 0xb9, 0x0d,
|
|
28
|
+
0x22, 0xc3, 0x1c, 0x07, 0x46, 0x69, 0xdc, 0xbf, 0x86, 0x7e, 0xb5, 0x21,
|
|
29
|
+
0xf4, 0xa3, 0x50, 0x30, 0x6f, 0x76, 0xb0, 0x71, 0x41, 0x9e, 0xbd, 0x78,
|
|
30
|
+
0xc5, 0xe9, 0xf4, 0x83, 0xc2, 0xfb, 0x64, 0x54, 0xe3, 0x51, 0x7d, 0x81,
|
|
31
|
+
0x53, 0x19, 0x0b, 0x8a, 0xde, 0x43, 0x4d, 0x63, 0x01, 0x91, 0x92, 0x4f,
|
|
32
|
+
0xc0, 0xfc, 0xf3, 0xe8, 0x9e, 0x50, 0xda, 0x9d, 0xc7, 0xcb, 0xba, 0x14,
|
|
33
|
+
0x9b, 0x83, 0xbb, 0xb3, 0xa6, 0xb5, 0x60, 0xcc, 0x50, 0x4b, 0xc2, 0xf8,
|
|
34
|
+
0x5e, 0xbc, 0x7c, 0x29, 0x3e, 0xda, 0x00, 0xe8, 0x4e, 0x81, 0x80, 0xa7,
|
|
35
|
+
0x23, 0xe3, 0xd1, 0x84, 0x71, 0x68, 0xde, 0x8f, 0x65, 0x7b, 0xef, 0x7a,
|
|
36
|
+
0xa3, 0x2c, 0x3b, 0x8f, 0x1b, 0xf9, 0x43, 0xe3, 0x77, 0x02, 0x03, 0x01,
|
|
37
|
+
0x00, 0x01, 0xa3, 0x60, 0x30, 0x5e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d,
|
|
38
|
+
0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, 0x8d, 0xf0, 0x48, 0x40, 0x1d, 0x7b,
|
|
39
|
+
0x71, 0x7f, 0xa3, 0x98, 0x32, 0x5d, 0x2b, 0x20, 0xb9, 0x09, 0xd5, 0x2b,
|
|
40
|
+
0xa7, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
|
|
41
|
+
0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d,
|
|
42
|
+
0x11, 0x04, 0x15, 0x30, 0x13, 0x86, 0x11, 0x72, 0x75, 0x62, 0x79, 0x2d,
|
|
43
|
+
0x6f, 0x70, 0x63, 0x75, 0x61, 0x3a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
|
44
|
+
0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04,
|
|
45
|
+
0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
|
46
|
+
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
|
|
47
|
+
0x48, 0x4b, 0x50, 0xfa, 0xbd, 0x8e, 0x7a, 0x66, 0x27, 0x84, 0xca, 0xb9,
|
|
48
|
+
0x46, 0xaf, 0xee, 0x87, 0x5c, 0xe3, 0x8b, 0xd8, 0x01, 0x0e, 0x62, 0xe9,
|
|
49
|
+
0xdf, 0x7d, 0xc3, 0xe4, 0x17, 0xcb, 0x70, 0xcc, 0xc9, 0x45, 0x00, 0x0c,
|
|
50
|
+
0xbe, 0xd8, 0xf3, 0x4e, 0xfd, 0xc8, 0x65, 0x6a, 0x1c, 0x0d, 0x9a, 0x19,
|
|
51
|
+
0x4b, 0xcb, 0x3a, 0xa3, 0x2c, 0xd5, 0xf6, 0x3c, 0xa9, 0x4e, 0x8c, 0x22,
|
|
52
|
+
0x49, 0xcf, 0x20, 0x54, 0x99, 0xe4, 0xfb, 0x60, 0x56, 0x17, 0xe5, 0x2a,
|
|
53
|
+
0x75, 0x2a, 0xb1, 0xcd, 0x24, 0x10, 0xce, 0x3f, 0xc2, 0x5f, 0xcc, 0x79,
|
|
54
|
+
0x30, 0x74, 0xb5, 0x23, 0xe7, 0x56, 0xad, 0x4f, 0x20, 0x91, 0xcb, 0x65,
|
|
55
|
+
0x87, 0x5d, 0x08, 0x6b, 0x19, 0xae, 0x68, 0x49, 0xaf, 0x1d, 0xe0, 0xff,
|
|
56
|
+
0x9c, 0xd5, 0xd4, 0x50, 0x61, 0x41, 0x7b, 0xa1, 0x93, 0xfe, 0x83, 0xe1,
|
|
57
|
+
0xba, 0x5e, 0xdb, 0x84, 0x81, 0xfa, 0x8a, 0xf6, 0x0a, 0x4a, 0xa6, 0xfb,
|
|
58
|
+
0x10, 0x7e, 0xff, 0x0b, 0x22, 0x18, 0x62, 0x3d, 0x88, 0xed, 0xe3, 0x7e,
|
|
59
|
+
0x92, 0xc7, 0x2d, 0x72, 0x6b, 0xf1, 0xc3, 0xa7, 0xed, 0x29, 0xa6, 0x39,
|
|
60
|
+
0xd9, 0xc8, 0xed, 0xa9, 0x05, 0x6e, 0xcc, 0x63, 0x96, 0xa4, 0x3a, 0x05,
|
|
61
|
+
0x38, 0x46, 0xc9, 0x72, 0x54, 0xb5, 0x5a, 0x05, 0x54, 0xe6, 0x97, 0x3d,
|
|
62
|
+
0xc8, 0xdd, 0xba, 0x9c, 0xfd, 0x0c, 0xbc, 0x0c, 0x44, 0x4b, 0x7f, 0xd1,
|
|
63
|
+
0x84, 0xcc, 0xb0, 0x65, 0x4b, 0xdb, 0x4b, 0x25, 0x6d, 0xca, 0x08, 0x90,
|
|
64
|
+
0x07, 0xde, 0x6a, 0x7d, 0x93, 0x79, 0xb0, 0x4d, 0xd6, 0xed, 0x30, 0x07,
|
|
65
|
+
0x14, 0xfd, 0x80, 0x7f, 0x54, 0xda, 0xbf, 0x11, 0x79, 0xd2, 0xa2, 0xea,
|
|
66
|
+
0x0a, 0xb6, 0x34, 0x1f, 0xb3, 0x22, 0xe9, 0x2b, 0x53, 0x5e, 0x11, 0x2e,
|
|
67
|
+
0x7e, 0x50, 0x4b, 0x09, 0x22, 0x53, 0x0b, 0xfb, 0x93, 0x8d, 0xec, 0x18,
|
|
68
|
+
0x45, 0x0e, 0x49, 0xb0
|
|
69
|
+
};
|
|
70
|
+
unsigned int cert_der_len = 796;
|
data/cert/cert_key.h
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
unsigned char cert_key_der[] = {
|
|
2
|
+
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
|
|
3
|
+
0xf5, 0x91, 0xb2, 0x9b, 0x5a, 0x5a, 0x7f, 0xac, 0xc1, 0xfd, 0x5f, 0x2e,
|
|
4
|
+
0xc1, 0x6c, 0x2b, 0x89, 0x84, 0x04, 0x0f, 0xae, 0x4c, 0xc2, 0x26, 0x86,
|
|
5
|
+
0xc8, 0x45, 0xcd, 0x71, 0x1c, 0xa2, 0x30, 0x54, 0xcb, 0x40, 0xeb, 0x30,
|
|
6
|
+
0xdf, 0xbb, 0x6a, 0x4e, 0x95, 0x1d, 0x57, 0xeb, 0xed, 0xa0, 0x30, 0xe1,
|
|
7
|
+
0x8f, 0x9d, 0x0b, 0xb0, 0x55, 0x18, 0x98, 0xef, 0xd6, 0x36, 0xa5, 0xe5,
|
|
8
|
+
0x4c, 0x88, 0xa1, 0xb7, 0x29, 0x08, 0xec, 0xa3, 0x7b, 0xac, 0x30, 0x20,
|
|
9
|
+
0x9a, 0xd2, 0x5a, 0x2d, 0x2f, 0x22, 0x08, 0x1b, 0x94, 0x97, 0x4d, 0xdf,
|
|
10
|
+
0xc1, 0x1d, 0x20, 0xb3, 0x9b, 0x9e, 0x7b, 0x58, 0xb3, 0xf0, 0xe8, 0x29,
|
|
11
|
+
0x25, 0x41, 0xf5, 0x54, 0x50, 0xde, 0x83, 0xef, 0x31, 0xae, 0xae, 0xb7,
|
|
12
|
+
0xbd, 0x0a, 0xbb, 0x19, 0x35, 0xc2, 0x6b, 0x3b, 0xe5, 0x36, 0x24, 0xf2,
|
|
13
|
+
0xf9, 0xe9, 0xe6, 0xa2, 0xe7, 0xe2, 0x50, 0xfe, 0x19, 0xbd, 0x9f, 0x51,
|
|
14
|
+
0xbd, 0x0f, 0xfe, 0x2c, 0xf5, 0x91, 0x5a, 0x5a, 0xe1, 0x53, 0xe2, 0x44,
|
|
15
|
+
0x4d, 0x31, 0x5c, 0x80, 0xbd, 0xb9, 0x0d, 0x22, 0xc3, 0x1c, 0x07, 0x46,
|
|
16
|
+
0x69, 0xdc, 0xbf, 0x86, 0x7e, 0xb5, 0x21, 0xf4, 0xa3, 0x50, 0x30, 0x6f,
|
|
17
|
+
0x76, 0xb0, 0x71, 0x41, 0x9e, 0xbd, 0x78, 0xc5, 0xe9, 0xf4, 0x83, 0xc2,
|
|
18
|
+
0xfb, 0x64, 0x54, 0xe3, 0x51, 0x7d, 0x81, 0x53, 0x19, 0x0b, 0x8a, 0xde,
|
|
19
|
+
0x43, 0x4d, 0x63, 0x01, 0x91, 0x92, 0x4f, 0xc0, 0xfc, 0xf3, 0xe8, 0x9e,
|
|
20
|
+
0x50, 0xda, 0x9d, 0xc7, 0xcb, 0xba, 0x14, 0x9b, 0x83, 0xbb, 0xb3, 0xa6,
|
|
21
|
+
0xb5, 0x60, 0xcc, 0x50, 0x4b, 0xc2, 0xf8, 0x5e, 0xbc, 0x7c, 0x29, 0x3e,
|
|
22
|
+
0xda, 0x00, 0xe8, 0x4e, 0x81, 0x80, 0xa7, 0x23, 0xe3, 0xd1, 0x84, 0x71,
|
|
23
|
+
0x68, 0xde, 0x8f, 0x65, 0x7b, 0xef, 0x7a, 0xa3, 0x2c, 0x3b, 0x8f, 0x1b,
|
|
24
|
+
0xf9, 0x43, 0xe3, 0x77, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
|
|
25
|
+
0x01, 0x00, 0xb8, 0x94, 0x26, 0xd7, 0xb6, 0x76, 0x47, 0x79, 0x26, 0xe6,
|
|
26
|
+
0xb7, 0x60, 0x81, 0x6a, 0x38, 0xdf, 0x48, 0x27, 0x75, 0x51, 0xe1, 0xc8,
|
|
27
|
+
0x1d, 0x05, 0x3a, 0x0b, 0x9d, 0x7b, 0xe3, 0xb5, 0xd4, 0xf6, 0x27, 0x40,
|
|
28
|
+
0x48, 0x87, 0x97, 0xe3, 0x5a, 0xe8, 0x6e, 0x14, 0x7c, 0x3d, 0x8d, 0x82,
|
|
29
|
+
0xd6, 0xba, 0xf4, 0x23, 0x6a, 0xe1, 0xc3, 0x54, 0x95, 0xbf, 0xd0, 0x17,
|
|
30
|
+
0x8b, 0x62, 0x6a, 0xc0, 0x58, 0x2d, 0x3f, 0xde, 0xc1, 0x5f, 0xb0, 0x59,
|
|
31
|
+
0xa0, 0x63, 0x21, 0x7b, 0xf2, 0xe3, 0xfb, 0x85, 0x6c, 0xea, 0xae, 0x29,
|
|
32
|
+
0x7c, 0x13, 0x2f, 0x28, 0x21, 0xa8, 0x5e, 0xd4, 0x24, 0x8a, 0x6b, 0xd6,
|
|
33
|
+
0x2b, 0xea, 0xa1, 0x62, 0x8e, 0x70, 0x2d, 0xc8, 0xd3, 0x0a, 0x3b, 0x21,
|
|
34
|
+
0xbd, 0x99, 0xc5, 0xb2, 0x07, 0x27, 0xcf, 0xcc, 0xae, 0xa5, 0x7a, 0x87,
|
|
35
|
+
0xd4, 0x05, 0xfd, 0xea, 0xdd, 0xbc, 0x9c, 0xe6, 0xf3, 0x50, 0x52, 0x3f,
|
|
36
|
+
0x8a, 0x67, 0xbe, 0x7e, 0xf9, 0xb5, 0xdb, 0x6d, 0x78, 0xf1, 0x57, 0x79,
|
|
37
|
+
0x8f, 0x7c, 0xe6, 0x5a, 0xba, 0xfc, 0x9b, 0x7a, 0x1b, 0x2c, 0x19, 0x14,
|
|
38
|
+
0xdb, 0x11, 0x69, 0x21, 0x96, 0xd8, 0x98, 0x5e, 0x38, 0x57, 0xe4, 0x54,
|
|
39
|
+
0xa0, 0x52, 0xd6, 0x08, 0x2c, 0x84, 0x01, 0x9d, 0x16, 0xac, 0x42, 0xe6,
|
|
40
|
+
0xaa, 0x18, 0x89, 0xa1, 0xc4, 0xfb, 0x4d, 0x66, 0xc8, 0x1e, 0x01, 0x69,
|
|
41
|
+
0xb0, 0xc1, 0x49, 0xfd, 0x73, 0x30, 0x22, 0xbf, 0x83, 0xe5, 0x4e, 0x17,
|
|
42
|
+
0x5a, 0x8a, 0x7b, 0x81, 0xc8, 0x60, 0x7a, 0x1e, 0x4a, 0xaf, 0x64, 0xd2,
|
|
43
|
+
0x63, 0xd8, 0xf6, 0xe9, 0x23, 0xaf, 0x5f, 0x02, 0x5e, 0xb5, 0xf9, 0xf8,
|
|
44
|
+
0x1d, 0xfb, 0x8f, 0x60, 0xa8, 0xcc, 0x24, 0x78, 0xd0, 0xc7, 0x25, 0x62,
|
|
45
|
+
0xc2, 0x66, 0x0d, 0xca, 0x0d, 0xab, 0xd1, 0x5c, 0x1e, 0xa9, 0x72, 0x4f,
|
|
46
|
+
0xe9, 0x34, 0xb4, 0xde, 0x78, 0xe1, 0x02, 0x81, 0x81, 0x00, 0xfd, 0x59,
|
|
47
|
+
0xbb, 0x02, 0xdc, 0x43, 0x51, 0xb9, 0x36, 0x08, 0x05, 0xc4, 0xf0, 0xca,
|
|
48
|
+
0x49, 0x74, 0xfc, 0x5c, 0xd6, 0x25, 0x0c, 0x7d, 0x9d, 0x7e, 0x9e, 0x1f,
|
|
49
|
+
0x2b, 0x2b, 0xad, 0xf8, 0x48, 0xd8, 0x4f, 0x9d, 0xf2, 0x42, 0x11, 0x80,
|
|
50
|
+
0xe9, 0x9d, 0xa0, 0x8c, 0x86, 0x1f, 0xad, 0xb5, 0x1d, 0x18, 0x25, 0xfb,
|
|
51
|
+
0xc0, 0x04, 0x18, 0xc3, 0xbf, 0x14, 0x2e, 0xe9, 0x2b, 0x0b, 0xbb, 0x93,
|
|
52
|
+
0x41, 0xde, 0x4a, 0xc2, 0x46, 0xf7, 0x99, 0x6e, 0xcc, 0x4c, 0x55, 0x57,
|
|
53
|
+
0x64, 0xb7, 0x74, 0xe9, 0xbe, 0x3b, 0xbb, 0xab, 0x2d, 0xb9, 0xf1, 0x7a,
|
|
54
|
+
0x1f, 0x37, 0x4a, 0xc9, 0xab, 0x8b, 0xdb, 0x40, 0x90, 0x9c, 0x9a, 0x45,
|
|
55
|
+
0x11, 0x6a, 0x70, 0xf8, 0x10, 0xbb, 0xf5, 0x4d, 0xd9, 0x91, 0x6a, 0x64,
|
|
56
|
+
0x21, 0x36, 0xf4, 0x5d, 0x81, 0x33, 0xb3, 0xed, 0x86, 0x69, 0xfd, 0x9c,
|
|
57
|
+
0x5d, 0xc5, 0x47, 0x05, 0x09, 0x85, 0x02, 0x81, 0x81, 0x00, 0xf8, 0x23,
|
|
58
|
+
0x22, 0x87, 0x7f, 0xbf, 0xa3, 0x82, 0x55, 0xd0, 0x5c, 0x23, 0x45, 0xd0,
|
|
59
|
+
0x6d, 0x04, 0xab, 0x07, 0x9d, 0x2a, 0x69, 0xaa, 0xbd, 0x80, 0x13, 0x9a,
|
|
60
|
+
0xb3, 0x1e, 0xc4, 0x06, 0x8e, 0x33, 0x5f, 0xe2, 0xa6, 0xf7, 0x54, 0xe6,
|
|
61
|
+
0x2e, 0x65, 0x9f, 0xde, 0x6e, 0xd2, 0x4a, 0xfe, 0xf5, 0xea, 0x8a, 0x5a,
|
|
62
|
+
0x9b, 0x61, 0x52, 0x49, 0x5e, 0x0d, 0x11, 0xe5, 0x9b, 0xdf, 0x2b, 0x5f,
|
|
63
|
+
0x89, 0x5d, 0x20, 0x7b, 0xa8, 0x7e, 0x2e, 0xda, 0x88, 0xfb, 0x1e, 0xa8,
|
|
64
|
+
0xac, 0x38, 0x66, 0x02, 0xda, 0xeb, 0xa6, 0xf6, 0x53, 0xa2, 0x26, 0x96,
|
|
65
|
+
0x6e, 0x7a, 0xf5, 0xc0, 0xb5, 0xea, 0x87, 0x7d, 0xd2, 0xb5, 0x83, 0x13,
|
|
66
|
+
0x26, 0xc7, 0x19, 0x60, 0x06, 0x4c, 0x87, 0x39, 0xa8, 0x0c, 0xf6, 0xf9,
|
|
67
|
+
0x8f, 0x55, 0xe4, 0xd1, 0xbc, 0x32, 0xbe, 0x17, 0x9d, 0x57, 0xf6, 0xac,
|
|
68
|
+
0xda, 0x4c, 0x2a, 0xbc, 0x2b, 0xcb, 0x02, 0x81, 0x81, 0x00, 0x97, 0x78,
|
|
69
|
+
0xe1, 0x8d, 0xc9, 0x41, 0x5a, 0x88, 0x20, 0x9c, 0xd5, 0x4e, 0x35, 0x24,
|
|
70
|
+
0xcc, 0x9c, 0x6c, 0x11, 0xd9, 0x5a, 0xd7, 0x47, 0xf7, 0x34, 0xef, 0xb6,
|
|
71
|
+
0xf4, 0xe9, 0xad, 0x9e, 0xe7, 0x76, 0xa4, 0xcb, 0x6b, 0x3f, 0x43, 0x15,
|
|
72
|
+
0xcf, 0x17, 0x16, 0x19, 0x4e, 0x4b, 0x7c, 0x60, 0xef, 0x9f, 0x33, 0x7e,
|
|
73
|
+
0x7c, 0x04, 0x37, 0x06, 0x39, 0xa5, 0x08, 0x93, 0x11, 0xd0, 0x76, 0xfa,
|
|
74
|
+
0x89, 0x04, 0x2d, 0xb0, 0x50, 0x1b, 0xd3, 0x19, 0x62, 0x7e, 0x34, 0xfc,
|
|
75
|
+
0x06, 0x54, 0x85, 0x4b, 0x07, 0x18, 0xd1, 0x90, 0x7b, 0xcb, 0x53, 0x6b,
|
|
76
|
+
0xcf, 0x64, 0x10, 0x8b, 0xd8, 0xcb, 0xca, 0x6f, 0xa4, 0xc6, 0x6c, 0x99,
|
|
77
|
+
0xe4, 0xda, 0xbd, 0xe6, 0x22, 0xa3, 0x2d, 0xfb, 0xb8, 0x9b, 0xef, 0x7f,
|
|
78
|
+
0x24, 0x38, 0xa6, 0x0b, 0x8d, 0xa6, 0xea, 0xe9, 0x95, 0x56, 0xa3, 0x71,
|
|
79
|
+
0xac, 0xc2, 0xb9, 0x3e, 0x72, 0xbd, 0x02, 0x81, 0x80, 0x4a, 0x11, 0xda,
|
|
80
|
+
0xdd, 0xcd, 0xb1, 0x7b, 0xf2, 0x8d, 0x01, 0x2c, 0x6f, 0xcf, 0x08, 0x3f,
|
|
81
|
+
0x72, 0xb4, 0x47, 0x0a, 0x90, 0x3d, 0x88, 0x9d, 0x16, 0x9d, 0x43, 0x81,
|
|
82
|
+
0x92, 0x7e, 0x7b, 0x62, 0x79, 0x4d, 0x77, 0x0f, 0xd6, 0x26, 0xbe, 0xab,
|
|
83
|
+
0x3c, 0xe4, 0xb2, 0xf6, 0x2b, 0xc9, 0xfd, 0x3f, 0x95, 0x2a, 0x85, 0x8f,
|
|
84
|
+
0x7a, 0x46, 0xa0, 0xe5, 0xf5, 0x4a, 0xd1, 0x5a, 0x6d, 0x0c, 0xba, 0x70,
|
|
85
|
+
0xfb, 0x9e, 0x95, 0xab, 0x1f, 0x37, 0x87, 0x3e, 0x7a, 0x8f, 0x95, 0x54,
|
|
86
|
+
0x0b, 0x65, 0xd0, 0x16, 0x5f, 0x5f, 0xb0, 0x8a, 0x18, 0x8e, 0x22, 0x3b,
|
|
87
|
+
0x8a, 0x72, 0xcf, 0x7a, 0xbe, 0x2e, 0x81, 0xcd, 0xa3, 0x27, 0x24, 0x51,
|
|
88
|
+
0x5f, 0xff, 0x60, 0x1d, 0xa1, 0x3c, 0x80, 0x66, 0x7c, 0xb0, 0x40, 0xa0,
|
|
89
|
+
0x9b, 0xc8, 0x39, 0x1f, 0x4f, 0x9a, 0x54, 0xdc, 0x40, 0x04, 0xbf, 0x66,
|
|
90
|
+
0x4e, 0x74, 0x37, 0x45, 0x6f, 0x02, 0x81, 0x80, 0x1d, 0x1c, 0x46, 0xd1,
|
|
91
|
+
0x0f, 0xfa, 0xf6, 0x94, 0xf2, 0xeb, 0x4e, 0x70, 0x6b, 0x2c, 0x10, 0xb1,
|
|
92
|
+
0xc9, 0x01, 0x8f, 0x0b, 0xf1, 0xe7, 0xee, 0xff, 0x86, 0x4f, 0x99, 0x49,
|
|
93
|
+
0x45, 0x8f, 0x2a, 0x48, 0x8b, 0xa8, 0x58, 0x24, 0x6b, 0x94, 0x89, 0x47,
|
|
94
|
+
0x5b, 0x41, 0x47, 0x5d, 0xd4, 0x36, 0x66, 0x39, 0x72, 0xf6, 0x62, 0xc4,
|
|
95
|
+
0x80, 0x04, 0x63, 0xa1, 0x6c, 0x7b, 0xd6, 0x81, 0x13, 0x28, 0x9d, 0x49,
|
|
96
|
+
0x4d, 0xa7, 0xc1, 0x00, 0x08, 0xbe, 0x3e, 0xbe, 0x90, 0x11, 0xae, 0x6f,
|
|
97
|
+
0xbf, 0x56, 0x32, 0x43, 0x95, 0x8c, 0x5a, 0xe0, 0x60, 0xe6, 0x06, 0x47,
|
|
98
|
+
0x84, 0xc4, 0x8c, 0xc4, 0xe2, 0xc6, 0x39, 0x0a, 0x63, 0x6a, 0x94, 0x36,
|
|
99
|
+
0xf7, 0xe4, 0x78, 0x18, 0x14, 0xfb, 0xfb, 0xe1, 0x66, 0xa0, 0xe3, 0x1d,
|
|
100
|
+
0x14, 0x62, 0xe4, 0x5d, 0x29, 0xb9, 0x41, 0x63, 0x5e, 0xe7, 0x88, 0xe4,
|
|
101
|
+
0xe6, 0xa7, 0x16, 0x8e
|
|
102
|
+
};
|
|
103
|
+
unsigned int cert_key_der_len = 1192;
|
data/example/client.rb
CHANGED
data/example/server.rb
CHANGED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
#include "client.h"
|
|
2
|
+
#include "../../../cert/cert.h"
|
|
3
|
+
#include "../../../cert/cert_key.h"
|
|
4
|
+
|
|
5
|
+
VALUE mOPCUA = Qnil;
|
|
6
|
+
VALUE cClient = Qnil;
|
|
7
|
+
VALUE cNode = Qnil;
|
|
8
|
+
|
|
9
|
+
void UA_Log_None_log(void *_, UA_LogLevel level, UA_LogCategory category, const char *msg, va_list args) { }
|
|
10
|
+
void UA_Log_None_clear(void *logContext) { }
|
|
11
|
+
const UA_Logger UA_Log_None_ = {UA_Log_None_log, NULL, UA_Log_None_clear};
|
|
12
|
+
const UA_Logger *UA_Log_None = &UA_Log_None_;
|
|
13
|
+
|
|
14
|
+
/* -- */
|
|
15
|
+
static VALUE extract_value(UA_Variant value) { //{{{
|
|
16
|
+
VALUE ret = rb_ary_new2(2);
|
|
17
|
+
rb_ary_store(ret,0,Qnil);
|
|
18
|
+
rb_ary_store(ret,1,Qnil);
|
|
19
|
+
if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) {
|
|
20
|
+
UA_DateTime raw = *(UA_DateTime *) value.data;
|
|
21
|
+
rb_ary_store(ret,0,rb_time_new(UA_DateTime_toUnixTime(raw),0));
|
|
22
|
+
rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.Double")));
|
|
23
|
+
} else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_BOOLEAN])) {
|
|
24
|
+
UA_Boolean raw = *(UA_Boolean *) value.data;
|
|
25
|
+
rb_ary_store(ret,0,raw ? Qtrue : Qfalse);
|
|
26
|
+
rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.Boolean")));
|
|
27
|
+
} else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DOUBLE])) {
|
|
28
|
+
UA_Double raw = *(UA_Double *) value.data;
|
|
29
|
+
rb_ary_store(ret,0,DBL2NUM(raw));
|
|
30
|
+
rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.Double")));
|
|
31
|
+
} else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_STRING])) {
|
|
32
|
+
UA_String raw = *(UA_String *) value.data;
|
|
33
|
+
rb_ary_store(ret,0,rb_str_export_locale(rb_str_new((char *)(raw.data),raw.length)));
|
|
34
|
+
rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.String")));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return ret;
|
|
38
|
+
} //}}}
|
|
39
|
+
/* ++ */
|
|
40
|
+
|
|
41
|
+
/* -- */
|
|
42
|
+
static void node_free(node_struct *ns) { //{{{
|
|
43
|
+
if (ns != NULL) {
|
|
44
|
+
rb_gc_unregister_address(&ns->on_change);
|
|
45
|
+
free(ns);
|
|
46
|
+
}
|
|
47
|
+
} //}}}
|
|
48
|
+
static VALUE node_alloc(VALUE klass, client_struct *client, UA_NodeId nodeid) { //{{{
|
|
49
|
+
node_struct *ns;
|
|
50
|
+
ns = (node_struct *)malloc(sizeof(node_struct));
|
|
51
|
+
if (ns == NULL)
|
|
52
|
+
rb_raise(rb_eNoMemError, "No memory left for node.");
|
|
53
|
+
|
|
54
|
+
ns->client = client;
|
|
55
|
+
ns->id = nodeid;
|
|
56
|
+
ns->on_change = Qnil;
|
|
57
|
+
|
|
58
|
+
return Data_Wrap_Struct(klass, NULL, node_free, ns);
|
|
59
|
+
} //}}}
|
|
60
|
+
/* ++ */
|
|
61
|
+
static VALUE node_value(VALUE self) { //{{{
|
|
62
|
+
node_struct *ns;
|
|
63
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
64
|
+
if (!ns->client->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
65
|
+
|
|
66
|
+
UA_Variant value;
|
|
67
|
+
UA_Variant_init(&value);
|
|
68
|
+
UA_StatusCode retval = UA_Client_readValueAttribute(ns->client->client, ns->id, &value);
|
|
69
|
+
|
|
70
|
+
VALUE ret = Qnil;
|
|
71
|
+
if (retval == UA_STATUSCODE_GOOD) {
|
|
72
|
+
ret = extract_value(value);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
UA_Variant_clear(&value);
|
|
76
|
+
return rb_ary_entry(ret,0);
|
|
77
|
+
} //}}}
|
|
78
|
+
static VALUE node_on_change(VALUE self) { //{{{
|
|
79
|
+
node_struct *ns;
|
|
80
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
81
|
+
if (!ns->client->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
82
|
+
|
|
83
|
+
if (!rb_block_given_p())
|
|
84
|
+
rb_raise(rb_eArgError, "you need to supply a block with #on_change");
|
|
85
|
+
|
|
86
|
+
ns->on_change = rb_block_proc();
|
|
87
|
+
rb_gc_register_address(&ns->on_change);
|
|
88
|
+
|
|
89
|
+
rb_ary_push(ns->client->subs,self);
|
|
90
|
+
ns->client->subs_changed = true;
|
|
91
|
+
|
|
92
|
+
return self;
|
|
93
|
+
} //}}}
|
|
94
|
+
|
|
95
|
+
/* -- */
|
|
96
|
+
static void client_free(client_struct *pss) { //{{{
|
|
97
|
+
if (pss != NULL) {
|
|
98
|
+
if (!pss->firstrun) {
|
|
99
|
+
// do we need to delete the individual monResponse (#UA_MonitoredItemCreateResult_clear)?
|
|
100
|
+
UA_Client_Subscriptions_deleteSingle(pss->client,pss->subscription_response.subscriptionId);
|
|
101
|
+
}
|
|
102
|
+
UA_Client_disconnect(pss->client);
|
|
103
|
+
UA_Client_delete(pss->client);
|
|
104
|
+
free(pss);
|
|
105
|
+
}
|
|
106
|
+
} //}}}
|
|
107
|
+
static VALUE client_alloc(VALUE self) { //{{{
|
|
108
|
+
client_struct *pss;
|
|
109
|
+
pss = (client_struct *)malloc(sizeof(client_struct));
|
|
110
|
+
if (pss == NULL)
|
|
111
|
+
rb_raise(rb_eNoMemError, "No memory left for OPCUA client.");
|
|
112
|
+
|
|
113
|
+
pss->client = UA_Client_new();
|
|
114
|
+
pss->config = UA_Client_getConfig(pss->client);
|
|
115
|
+
pss->firstrun = true;
|
|
116
|
+
pss->started = true;
|
|
117
|
+
pss->debug = true;
|
|
118
|
+
pss->subs = rb_ary_new();
|
|
119
|
+
pss->subs_changed = false;
|
|
120
|
+
pss->subscription_interval = 500;
|
|
121
|
+
|
|
122
|
+
UA_CreateSubscriptionRequest_init(&pss->subscription_request);
|
|
123
|
+
pss->subscription_request.requestedPublishingInterval = pss->subscription_interval;
|
|
124
|
+
pss->subscription_request.requestedLifetimeCount = 10000;
|
|
125
|
+
pss->subscription_request.requestedMaxKeepAliveCount = 10;
|
|
126
|
+
pss->subscription_request.maxNotificationsPerPublish = 0;
|
|
127
|
+
pss->subscription_request.publishingEnabled = true;
|
|
128
|
+
pss->subscription_request.priority = 0;
|
|
129
|
+
|
|
130
|
+
return Data_Wrap_Struct(self, NULL, client_free, pss);
|
|
131
|
+
} //}}}
|
|
132
|
+
|
|
133
|
+
/* ++ */ //}}}
|
|
134
|
+
static VALUE client_init(VALUE self,VALUE url,VALUE user,VALUE pass) { //{{{
|
|
135
|
+
client_struct *pss;
|
|
136
|
+
UA_StatusCode retval;
|
|
137
|
+
|
|
138
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
139
|
+
|
|
140
|
+
VALUE str = rb_obj_as_string(url);
|
|
141
|
+
if (NIL_P(str) || TYPE(str) != T_STRING) {
|
|
142
|
+
pss->started = false;
|
|
143
|
+
rb_raise(rb_eTypeError, "cannot convert url to string");
|
|
144
|
+
}
|
|
145
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
146
|
+
|
|
147
|
+
UA_ByteString certificate;
|
|
148
|
+
certificate.data = (UA_Byte *)cert_der;
|
|
149
|
+
certificate.length = cert_der_len;
|
|
150
|
+
UA_ByteString privateKey;
|
|
151
|
+
privateKey.data = (UA_Byte *)cert_key_der;
|
|
152
|
+
privateKey.length = cert_key_der_len;
|
|
153
|
+
|
|
154
|
+
/* Load the trustList. Load revocationList is not supported now */
|
|
155
|
+
size_t trustListSize = 0;
|
|
156
|
+
UA_STACKARRAY(UA_ByteString, trustList, trustListSize);
|
|
157
|
+
|
|
158
|
+
UA_ByteString *revocationList = NULL;
|
|
159
|
+
size_t revocationListSize = 0;
|
|
160
|
+
|
|
161
|
+
UA_ClientConfig_setDefaultEncryption(pss->config, certificate, privateKey,
|
|
162
|
+
trustList, trustListSize,
|
|
163
|
+
revocationList, revocationListSize);
|
|
164
|
+
|
|
165
|
+
for(size_t deleteCount = 0; deleteCount < trustListSize; deleteCount++) {
|
|
166
|
+
UA_ByteString_clear(&trustList[deleteCount]);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
pss->config->securityMode = UA_MESSAGESECURITYMODE_NONE; /* require no encryption, but tokens might be still enc'd */
|
|
170
|
+
|
|
171
|
+
//{{{
|
|
172
|
+
// UA_ClientConfig_setDefault(pss->config);
|
|
173
|
+
// /* Listing endpoints */
|
|
174
|
+
// UA_EndpointDescription* endpointArray = NULL;
|
|
175
|
+
// size_t endpointArraySize = 0;
|
|
176
|
+
// retval = UA_Client_getEndpoints(pss->client, "opc.tcp://localhost:4840",
|
|
177
|
+
// &endpointArraySize, &endpointArray);
|
|
178
|
+
// if(retval != UA_STATUSCODE_GOOD) {
|
|
179
|
+
// UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
|
|
180
|
+
// UA_Client_delete(pss->client);
|
|
181
|
+
// return EXIT_FAILURE;
|
|
182
|
+
// }
|
|
183
|
+
// printf("%i endpoints found\n", (int)endpointArraySize);
|
|
184
|
+
|
|
185
|
+
// for(size_t i=0;i<endpointArraySize;i++) {
|
|
186
|
+
// printf("URL of endpoint %i is %.*s\n", (int)i,
|
|
187
|
+
// (int)endpointArray[i].endpointUrl.length,
|
|
188
|
+
// endpointArray[i].endpointUrl.data);
|
|
189
|
+
|
|
190
|
+
// printf("\tuserIdentityTokens\n");
|
|
191
|
+
// for(size_t j=0;j<endpointArray[i].userIdentityTokensSize;++j) {
|
|
192
|
+
// printf("\t\t");
|
|
193
|
+
// switch(endpointArray[i].userIdentityTokens[j].tokenType) {
|
|
194
|
+
// case UA_USERTOKENTYPE_ANONYMOUS:
|
|
195
|
+
// printf("Anonymous");
|
|
196
|
+
// break;
|
|
197
|
+
// case UA_USERTOKENTYPE_USERNAME:
|
|
198
|
+
// printf("Username");
|
|
199
|
+
// break;
|
|
200
|
+
// case UA_USERTOKENTYPE_CERTIFICATE:
|
|
201
|
+
// printf("Certificate");
|
|
202
|
+
// break;
|
|
203
|
+
// case UA_USERTOKENTYPE_ISSUEDTOKEN:
|
|
204
|
+
// printf("Issued Token");
|
|
205
|
+
// break;
|
|
206
|
+
// default:
|
|
207
|
+
// printf("No valid token type");
|
|
208
|
+
// break;
|
|
209
|
+
// }
|
|
210
|
+
// printf("(%s)\n",endpointArray[i].userIdentityTokens[j].securityPolicyUri.data);
|
|
211
|
+
// }
|
|
212
|
+
// }
|
|
213
|
+
// UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
|
|
214
|
+
//}}}
|
|
215
|
+
|
|
216
|
+
if (NIL_P(user) || NIL_P(pass)) {
|
|
217
|
+
retval = UA_Client_connect(pss->client,nstr);
|
|
218
|
+
} else {
|
|
219
|
+
VALUE vustr = rb_obj_as_string(user);
|
|
220
|
+
if (NIL_P(vustr) || TYPE(vustr) != T_STRING) {
|
|
221
|
+
pss->started = false;
|
|
222
|
+
rb_raise(rb_eTypeError, "cannot convert user to string");
|
|
223
|
+
}
|
|
224
|
+
char *ustr = (char *)StringValuePtr(vustr);
|
|
225
|
+
|
|
226
|
+
VALUE vpstr = rb_obj_as_string(pass);
|
|
227
|
+
if (NIL_P(vpstr) || TYPE(vpstr) != T_STRING) {
|
|
228
|
+
pss->started = false;
|
|
229
|
+
rb_raise(rb_eTypeError, "cannot convert user to string");
|
|
230
|
+
}
|
|
231
|
+
char *pstr = (char *)StringValuePtr(vpstr);
|
|
232
|
+
|
|
233
|
+
retval = UA_Client_connect_username(pss->client, nstr, ustr, pstr);
|
|
234
|
+
}
|
|
235
|
+
if (retval != UA_STATUSCODE_GOOD) {
|
|
236
|
+
pss->started = false;
|
|
237
|
+
rb_raise(rb_eRuntimeError, "Client could not be started.");
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return self;
|
|
241
|
+
} //}}}
|
|
242
|
+
static VALUE client_get(VALUE self,VALUE ns,VALUE id) { //{{{
|
|
243
|
+
client_struct *pss;
|
|
244
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
245
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
246
|
+
|
|
247
|
+
if (NIL_P(ns) || TYPE(ns) != T_FIXNUM)
|
|
248
|
+
rb_raise(rb_eTypeError, "ns is not a valid (numeric) namespace id");
|
|
249
|
+
if (TYPE(id) == T_FIXNUM) {
|
|
250
|
+
return node_alloc(cNode, pss, UA_NODEID_NUMERIC(NUM2INT(ns), NUM2INT(id)));
|
|
251
|
+
} else {
|
|
252
|
+
VALUE str = rb_obj_as_string(id);
|
|
253
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
254
|
+
rb_raise(rb_eTypeError, "cannot convert url to string");
|
|
255
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
256
|
+
|
|
257
|
+
return node_alloc(cNode, pss, UA_NODEID_STRING(NUM2INT(ns), nstr));
|
|
258
|
+
}
|
|
259
|
+
} //}}}
|
|
260
|
+
static VALUE client_subscription_interval(VALUE self) { //{{{
|
|
261
|
+
client_struct *pss;
|
|
262
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
263
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
264
|
+
|
|
265
|
+
return UINT2NUM(pss->subscription_request.requestedPublishingInterval);
|
|
266
|
+
} //}}}
|
|
267
|
+
static VALUE client_subscription_interval_set(VALUE self, VALUE val) { //{{{
|
|
268
|
+
client_struct *pss;
|
|
269
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
270
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
271
|
+
|
|
272
|
+
if (NIL_P(val) || TYPE(val) != T_FIXNUM)
|
|
273
|
+
rb_raise(rb_eTypeError, "subscription interval is not an integer");
|
|
274
|
+
|
|
275
|
+
pss->subscription_request.requestedPublishingInterval = NUM2UINT(val);
|
|
276
|
+
return self;
|
|
277
|
+
} //}}}
|
|
278
|
+
static VALUE client_debug(VALUE self) { //{{{
|
|
279
|
+
client_struct *pss;
|
|
280
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
281
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
282
|
+
|
|
283
|
+
return (pss->debug) ? Qtrue : Qfalse;
|
|
284
|
+
} //}}}
|
|
285
|
+
static VALUE client_debug_set(VALUE self, VALUE val) { //{{{
|
|
286
|
+
client_struct *pss;
|
|
287
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
288
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
289
|
+
|
|
290
|
+
if (val == Qtrue) {
|
|
291
|
+
pss->config->logger = UA_Log_Stdout_;
|
|
292
|
+
pss->debug = Qtrue;
|
|
293
|
+
} else {
|
|
294
|
+
pss->config->logger = UA_Log_None_;
|
|
295
|
+
pss->debug = Qfalse;
|
|
296
|
+
}
|
|
297
|
+
return self;
|
|
298
|
+
} //}}}
|
|
299
|
+
|
|
300
|
+
static void client_run_handler(UA_Client *client, UA_UInt32 subId, void *subContext, UA_UInt32 monId, void *monContext, UA_DataValue *value) { //{{{
|
|
301
|
+
VALUE val = (VALUE)monContext;
|
|
302
|
+
|
|
303
|
+
if (NIL_P(val) || TYPE(val) != T_NIL) {
|
|
304
|
+
VALUE args = rb_ary_new2(3);
|
|
305
|
+
VALUE ret = extract_value(value->value);
|
|
306
|
+
rb_ary_store(args,0,rb_ary_entry(ret,0));
|
|
307
|
+
if (value->hasSourceTimestamp) {
|
|
308
|
+
rb_ary_store(args,1,rb_time_new(UA_DateTime_toUnixTime(value->sourceTimestamp),0));
|
|
309
|
+
} else {
|
|
310
|
+
if (value->hasServerTimestamp) {
|
|
311
|
+
rb_ary_store(args,1,rb_time_new(UA_DateTime_toUnixTime(value->serverTimestamp),0));
|
|
312
|
+
} else {
|
|
313
|
+
rb_ary_store(args,1,Qnil);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
rb_ary_store(args,2,rb_ary_entry(ret,1));
|
|
317
|
+
rb_proc_call(val,args);
|
|
318
|
+
}
|
|
319
|
+
} //}}}
|
|
320
|
+
static void client_run_iterate(VALUE key) { //{{{
|
|
321
|
+
node_struct *ns;
|
|
322
|
+
Data_Get_Struct(key, node_struct, ns);
|
|
323
|
+
|
|
324
|
+
UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest_default(ns->id);
|
|
325
|
+
|
|
326
|
+
UA_MonitoredItemCreateResult monResponse =
|
|
327
|
+
UA_Client_MonitoredItems_createDataChange(ns->client->client, ns->client->subscription_response.subscriptionId,
|
|
328
|
+
UA_TIMESTAMPSTORETURN_BOTH,
|
|
329
|
+
monRequest, (void *)ns->on_change, client_run_handler, NULL);
|
|
330
|
+
|
|
331
|
+
if(monResponse.statusCode != UA_STATUSCODE_GOOD) {
|
|
332
|
+
rb_raise(rb_eRuntimeError, "Monitoring item failed: %s\n", UA_StatusCode_name(monResponse.statusCode));
|
|
333
|
+
}
|
|
334
|
+
} //}}}
|
|
335
|
+
static VALUE client_run(VALUE self) { //{{{
|
|
336
|
+
client_struct *pss;
|
|
337
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
338
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
339
|
+
|
|
340
|
+
if (pss->firstrun) {
|
|
341
|
+
pss->firstrun = false;
|
|
342
|
+
pss->subs_changed = false;
|
|
343
|
+
pss->subscription_response = UA_Client_Subscriptions_create(pss->client, pss->subscription_request, NULL, NULL, NULL);
|
|
344
|
+
if (pss->subscription_response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
|
|
345
|
+
rb_raise(rb_eRuntimeError, "Subscription could not be created.");
|
|
346
|
+
|
|
347
|
+
for (int i = 0; i < RARRAY_LEN(pss->subs); i++) {
|
|
348
|
+
client_run_iterate(rb_ary_entry(pss->subs,i));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
UA_Client_run_iterate(pss->client, 100);
|
|
352
|
+
|
|
353
|
+
return self;
|
|
354
|
+
} //}}}
|
|
355
|
+
static VALUE client_disconnect(VALUE self) { //{{{
|
|
356
|
+
client_struct *pss;
|
|
357
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
358
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
359
|
+
|
|
360
|
+
if (!pss->firstrun) {
|
|
361
|
+
// do we need to delete the individual monResponse (#UA_MonitoredItemCreateResult_clear)?
|
|
362
|
+
UA_Client_Subscriptions_deleteSingle(pss->client,pss->subscription_response.subscriptionId);
|
|
363
|
+
}
|
|
364
|
+
UA_Client_disconnect(pss->client);
|
|
365
|
+
pss->started = false;
|
|
366
|
+
|
|
367
|
+
return self;
|
|
368
|
+
} //}}}
|
|
369
|
+
|
|
370
|
+
void Init_client(void) {
|
|
371
|
+
mOPCUA = rb_define_module("OPCUA");
|
|
372
|
+
|
|
373
|
+
cClient = rb_define_class_under(mOPCUA, "Client", rb_cObject);
|
|
374
|
+
cNode = rb_define_class_under(mOPCUA, "cNode", rb_cObject);
|
|
375
|
+
|
|
376
|
+
rb_define_alloc_func(cClient, client_alloc);
|
|
377
|
+
rb_define_method(cClient, "initialize", client_init, 3);
|
|
378
|
+
rb_define_method(cClient, "disconnect", client_disconnect, 0);
|
|
379
|
+
rb_define_method(cClient, "get", client_get, 2);
|
|
380
|
+
rb_define_method(cClient, "check_subscription", client_run, 0);
|
|
381
|
+
rb_define_method(cClient, "subscription_interval", client_subscription_interval, 0);
|
|
382
|
+
rb_define_method(cClient, "subscription_interval=", client_subscription_interval_set, 1);
|
|
383
|
+
rb_define_method(cClient, "debug", client_debug, 0);
|
|
384
|
+
rb_define_method(cClient, "debug=", client_debug_set, 1);
|
|
385
|
+
|
|
386
|
+
rb_define_method(cNode, "value", node_value, 0);
|
|
387
|
+
rb_define_method(cNode, "on_change", node_on_change, 0);
|
|
388
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#include <ruby.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <open62541.h>
|
|
4
|
+
|
|
5
|
+
typedef struct client_struct {
|
|
6
|
+
UA_ClientConfig *config;
|
|
7
|
+
UA_Client *client;
|
|
8
|
+
UA_CreateSubscriptionRequest subscription_request;
|
|
9
|
+
UA_CreateSubscriptionResponse subscription_response;
|
|
10
|
+
|
|
11
|
+
UA_UInt32 subscription_interval;
|
|
12
|
+
bool firstrun;
|
|
13
|
+
bool started;
|
|
14
|
+
bool debug;
|
|
15
|
+
VALUE subs;
|
|
16
|
+
bool subs_changed;
|
|
17
|
+
} client_struct;
|
|
18
|
+
|
|
19
|
+
typedef struct node_struct {
|
|
20
|
+
client_struct *client;
|
|
21
|
+
VALUE on_change;
|
|
22
|
+
UA_NodeId id;
|
|
23
|
+
} node_struct;
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
#include "server.h"
|
|
2
|
+
|
|
3
|
+
VALUE mOPCUA = Qnil;
|
|
4
|
+
VALUE cServer = Qnil;
|
|
5
|
+
VALUE cObjectsNode = Qnil;
|
|
6
|
+
VALUE cTypesTopNode = Qnil;
|
|
7
|
+
VALUE cTypesSubNode = Qnil;
|
|
8
|
+
VALUE cLeafNode = Qnil;
|
|
9
|
+
|
|
10
|
+
/* -- */
|
|
11
|
+
static void node_free(node_struct *ns) { //{{{
|
|
12
|
+
if (ns != NULL) { free(ns); }
|
|
13
|
+
} //}}}
|
|
14
|
+
static VALUE node_alloc(VALUE klass, server_struct *server, UA_NodeId nodeid) { //{{{
|
|
15
|
+
node_struct *ns;
|
|
16
|
+
ns = (node_struct *)malloc(sizeof(node_struct));
|
|
17
|
+
if (ns == NULL)
|
|
18
|
+
rb_raise(rb_eNoMemError, "No memory left for node.");
|
|
19
|
+
|
|
20
|
+
ns->server = server;
|
|
21
|
+
ns->id = nodeid;
|
|
22
|
+
|
|
23
|
+
return Data_Wrap_Struct(klass, NULL, node_free, ns);
|
|
24
|
+
} //}}}
|
|
25
|
+
/* ++ */
|
|
26
|
+
static VALUE node_type_folder(VALUE self) { //{{{
|
|
27
|
+
node_struct *ns;
|
|
28
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
29
|
+
return node_alloc(cTypesTopNode, ns->server, UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
30
|
+
} //}}}
|
|
31
|
+
static VALUE node_add_object_type(VALUE self, VALUE name) { //{{{
|
|
32
|
+
node_struct *ns;
|
|
33
|
+
|
|
34
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
35
|
+
|
|
36
|
+
VALUE str = rb_obj_as_string(name);
|
|
37
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
38
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
39
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
40
|
+
|
|
41
|
+
UA_NodeId n = UA_NODEID_STRING(ns->server->default_ns, nstr);
|
|
42
|
+
|
|
43
|
+
UA_ObjectTypeAttributes dtAttr = UA_ObjectTypeAttributes_default;
|
|
44
|
+
dtAttr.displayName = UA_LOCALIZEDTEXT("en-US", nstr);
|
|
45
|
+
UA_Server_addObjectTypeNode(ns->server->server,
|
|
46
|
+
n,
|
|
47
|
+
ns->id,
|
|
48
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
|
|
49
|
+
UA_QUALIFIEDNAME(ns->server->default_ns, nstr),
|
|
50
|
+
dtAttr,
|
|
51
|
+
NULL,
|
|
52
|
+
NULL);
|
|
53
|
+
|
|
54
|
+
return node_alloc(cTypesSubNode,ns->server,n);
|
|
55
|
+
} //}}}
|
|
56
|
+
static VALUE node_add_variable(int argc, VALUE* argv, VALUE self) { //{{{
|
|
57
|
+
node_struct *ns;
|
|
58
|
+
|
|
59
|
+
if (argc > 2 || argc == 0) { // there should only be 1 or 2 arguments
|
|
60
|
+
rb_raise(rb_eArgError, "wrong number of arguments");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
UA_UInt32 type;
|
|
64
|
+
if (argc == 2 && argv[1] != Qnil) {
|
|
65
|
+
type = NUM2INT(argv[1]);
|
|
66
|
+
} else {
|
|
67
|
+
type = UA_NS0ID_MODELLINGRULE_MANDATORY;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
71
|
+
|
|
72
|
+
VALUE str = rb_obj_as_string(argv[0]);
|
|
73
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
74
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
75
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
76
|
+
|
|
77
|
+
UA_VariableAttributes mnAttr = UA_VariableAttributes_default;
|
|
78
|
+
mnAttr.displayName = UA_LOCALIZEDTEXT("en-US", nstr);
|
|
79
|
+
|
|
80
|
+
UA_NodeId n = UA_NODEID_STRING(ns->server->default_ns, nstr);
|
|
81
|
+
|
|
82
|
+
UA_Server_addVariableNode(ns->server->server,
|
|
83
|
+
n,
|
|
84
|
+
ns->id,
|
|
85
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
86
|
+
UA_QUALIFIEDNAME(ns->server->default_ns, nstr),
|
|
87
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
|
|
88
|
+
mnAttr,
|
|
89
|
+
NULL,
|
|
90
|
+
NULL);
|
|
91
|
+
|
|
92
|
+
if (argv[1] != Qnil) {
|
|
93
|
+
UA_Server_addReference(ns->server->server,
|
|
94
|
+
n,
|
|
95
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
|
|
96
|
+
UA_EXPANDEDNODEID_NUMERIC(0, type),
|
|
97
|
+
true);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return node_alloc(cLeafNode,ns->server,n);
|
|
101
|
+
} //}}}
|
|
102
|
+
static VALUE node_add_variable_without(VALUE self, VALUE name) { //{{{
|
|
103
|
+
VALUE argv[] = { name, Qnil };
|
|
104
|
+
return node_add_variable(2,argv,self);
|
|
105
|
+
} //}}}
|
|
106
|
+
static VALUE node_add_object(int argc, VALUE* argv, VALUE self) { //{{{
|
|
107
|
+
node_struct *ns;
|
|
108
|
+
node_struct *ts;
|
|
109
|
+
|
|
110
|
+
if (argc > 3 || argc < 2) { // there should only be 2 or 3 arguments
|
|
111
|
+
rb_raise(rb_eArgError, "wrong number of arguments");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
UA_UInt32 type;
|
|
115
|
+
if (argc == 3 && argv[2] != Qnil) {
|
|
116
|
+
type = NUM2INT(argv[2]);
|
|
117
|
+
} else {
|
|
118
|
+
type = UA_NS0ID_MODELLINGRULE_MANDATORY;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!(rb_obj_is_kind_of(argv[1],cTypesTopNode) || rb_obj_is_kind_of(argv[1],cTypesSubNode))) {
|
|
122
|
+
rb_raise(rb_eArgError, "argument 2 has to be a type.");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
126
|
+
Data_Get_Struct(argv[1], node_struct, ts);
|
|
127
|
+
|
|
128
|
+
VALUE str = rb_obj_as_string(argv[0]);
|
|
129
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
130
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
131
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
132
|
+
|
|
133
|
+
UA_NodeId n = UA_NODEID_STRING(ns->server->default_ns, nstr);
|
|
134
|
+
|
|
135
|
+
UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
|
|
136
|
+
oAttr.displayName = UA_LOCALIZEDTEXT("en-US", nstr);
|
|
137
|
+
UA_Server_addObjectNode(ns->server->server,
|
|
138
|
+
n,
|
|
139
|
+
ns->id,
|
|
140
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
141
|
+
UA_QUALIFIEDNAME(ns->server->default_ns, nstr),
|
|
142
|
+
ts->id,
|
|
143
|
+
oAttr,
|
|
144
|
+
NULL,
|
|
145
|
+
NULL);
|
|
146
|
+
|
|
147
|
+
if (argv[2] != Qnil) {
|
|
148
|
+
UA_Server_addReference(ns->server->server,
|
|
149
|
+
n,
|
|
150
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
|
|
151
|
+
UA_EXPANDEDNODEID_NUMERIC(0, type),
|
|
152
|
+
true);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return node_alloc(CLASS_OF(self),ns->server,n);
|
|
156
|
+
} //}}}
|
|
157
|
+
static VALUE node_add_object_without(VALUE self, VALUE name, VALUE parent) { //{{{
|
|
158
|
+
VALUE argv[] = { name, parent, Qnil };
|
|
159
|
+
return node_add_object(3,argv,self);
|
|
160
|
+
} //}}}
|
|
161
|
+
static VALUE node_find(VALUE self, VALUE qname) { //{{{
|
|
162
|
+
node_struct *ns;
|
|
163
|
+
|
|
164
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
165
|
+
|
|
166
|
+
VALUE str = rb_obj_as_string(qname);
|
|
167
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
168
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
169
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
170
|
+
|
|
171
|
+
/* Find the NodeId of the status child variable */
|
|
172
|
+
UA_RelativePathElement rpe;
|
|
173
|
+
UA_RelativePathElement_init(&rpe);
|
|
174
|
+
rpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
|
|
175
|
+
rpe.isInverse = false;
|
|
176
|
+
rpe.includeSubtypes = false;
|
|
177
|
+
rpe.targetName = UA_QUALIFIEDNAME(ns->server->default_ns, nstr);
|
|
178
|
+
|
|
179
|
+
UA_BrowsePath bp;
|
|
180
|
+
UA_BrowsePath_init(&bp);
|
|
181
|
+
bp.startingNode = ns->id;
|
|
182
|
+
bp.relativePath.elementsSize = 1;
|
|
183
|
+
bp.relativePath.elements = &rpe;
|
|
184
|
+
|
|
185
|
+
UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(ns->server->server, &bp);
|
|
186
|
+
|
|
187
|
+
if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
|
|
188
|
+
return Qnil;
|
|
189
|
+
} else {
|
|
190
|
+
UA_NodeId ret = bpr.targets[0].targetId.nodeId;
|
|
191
|
+
UA_BrowsePathResult_clear(&bpr);
|
|
192
|
+
return node_alloc(CLASS_OF(self),ns->server,ret);
|
|
193
|
+
}
|
|
194
|
+
} //}}}
|
|
195
|
+
|
|
196
|
+
static VALUE node_value_set(VALUE self, VALUE value) { //{{{
|
|
197
|
+
node_struct *ns;
|
|
198
|
+
|
|
199
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
200
|
+
|
|
201
|
+
UA_Variant variant;
|
|
202
|
+
if (rb_obj_is_kind_of(value,rb_cTime)) {
|
|
203
|
+
UA_DateTime tmp = UA_DateTime_fromUnixTime(rb_time_timeval(value).tv_sec);
|
|
204
|
+
UA_Variant_setScalar(&variant, &tmp, &UA_TYPES[UA_TYPES_DATETIME]);
|
|
205
|
+
UA_Server_writeValue(ns->server->server, ns->id, variant);
|
|
206
|
+
} else {
|
|
207
|
+
switch (TYPE(value)) {
|
|
208
|
+
case T_FALSE:
|
|
209
|
+
{
|
|
210
|
+
UA_Boolean tmp = false;
|
|
211
|
+
UA_Variant_setScalar(&variant, &tmp, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
|
212
|
+
UA_Server_writeValue(ns->server->server, ns->id, variant);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
case T_TRUE:
|
|
216
|
+
{
|
|
217
|
+
UA_Boolean tmp = true;
|
|
218
|
+
UA_Variant_setScalar(&variant, &tmp, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
|
219
|
+
UA_Server_writeValue(ns->server->server, ns->id, variant);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case T_FLOAT:
|
|
223
|
+
case T_FIXNUM:
|
|
224
|
+
{
|
|
225
|
+
UA_Double tmp = NUM2DBL(value);
|
|
226
|
+
UA_Variant_setScalar(&variant, &tmp, &UA_TYPES[UA_TYPES_DOUBLE]);
|
|
227
|
+
UA_Server_writeValue(ns->server->server, ns->id, variant);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
case T_STRING:
|
|
231
|
+
case T_SYMBOL:
|
|
232
|
+
{
|
|
233
|
+
VALUE str = rb_obj_as_string(value);
|
|
234
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
235
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
236
|
+
UA_String tmp = UA_STRING(StringValuePtr(str));
|
|
237
|
+
UA_Variant_setScalar(&variant, &tmp, &UA_TYPES[UA_TYPES_STRING]);
|
|
238
|
+
UA_Server_writeValue(ns->server->server, ns->id, variant);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return self;
|
|
244
|
+
} //}}}
|
|
245
|
+
static VALUE node_value(VALUE self) { //{{{
|
|
246
|
+
node_struct *ns;
|
|
247
|
+
|
|
248
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
249
|
+
|
|
250
|
+
UA_Variant value;
|
|
251
|
+
UA_Variant_init(&value);
|
|
252
|
+
UA_StatusCode retval = UA_Server_readValue(ns->server->server, ns->id, &value);
|
|
253
|
+
|
|
254
|
+
VALUE ret = Qnil;
|
|
255
|
+
if (retval == UA_STATUSCODE_GOOD) {
|
|
256
|
+
if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) {
|
|
257
|
+
UA_DateTime raw = *(UA_DateTime *) value.data;
|
|
258
|
+
ret = rb_time_new(UA_DateTime_toUnixTime(raw),0);
|
|
259
|
+
} else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_BOOLEAN])) {
|
|
260
|
+
UA_Boolean raw = *(UA_Boolean *) value.data;
|
|
261
|
+
ret = raw ? Qtrue : Qfalse;
|
|
262
|
+
} else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DOUBLE])) {
|
|
263
|
+
UA_Double raw = *(UA_Double *) value.data;
|
|
264
|
+
ret = DBL2NUM(raw);
|
|
265
|
+
} else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_STRING])) {
|
|
266
|
+
UA_String raw = *(UA_String *) value.data;
|
|
267
|
+
ret = rb_str_new((char *)(raw.data),raw.length);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
UA_Variant_clear(&value);
|
|
272
|
+
return ret;
|
|
273
|
+
} //}}}
|
|
274
|
+
static VALUE node_id(VALUE self) { //{{{
|
|
275
|
+
node_struct *ns;
|
|
276
|
+
|
|
277
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
278
|
+
|
|
279
|
+
VALUE ret = rb_ary_new();
|
|
280
|
+
|
|
281
|
+
rb_ary_push(ret,UINT2NUM(ns->id.namespaceIndex));
|
|
282
|
+
if (ns->id.identifierType == UA_NODEIDTYPE_NUMERIC) {
|
|
283
|
+
VALUE id = UINT2NUM((UA_UInt32)(ns->id.identifier.numeric));
|
|
284
|
+
rb_ary_push(ret,id);
|
|
285
|
+
} else if (ns->id.identifierType == UA_NODEIDTYPE_STRING) {
|
|
286
|
+
rb_ary_push(ret,rb_str_new((const char *)ns->id.identifier.string.data,ns->id.identifier.string.length));
|
|
287
|
+
} else if (ns->id.identifierType == UA_NODEIDTYPE_BYTESTRING) {
|
|
288
|
+
rb_ary_push(ret,rb_str_new((const char *)ns->id.identifier.byteString.data,ns->id.identifier.byteString.length));
|
|
289
|
+
}
|
|
290
|
+
return ret;
|
|
291
|
+
} //}}}
|
|
292
|
+
/* -- */
|
|
293
|
+
static void server_free(server_struct *pss) { //{{{
|
|
294
|
+
if (pss != NULL) {
|
|
295
|
+
UA_Server_delete(pss->server);
|
|
296
|
+
free(pss);
|
|
297
|
+
}
|
|
298
|
+
} //}}}
|
|
299
|
+
static VALUE server_alloc(VALUE self) { //{{{
|
|
300
|
+
server_struct *pss;
|
|
301
|
+
pss = (server_struct *)malloc(sizeof(server_struct));
|
|
302
|
+
if (pss == NULL)
|
|
303
|
+
rb_raise(rb_eNoMemError, "No memory left for OPCUA server.");
|
|
304
|
+
|
|
305
|
+
pss->server = UA_Server_new();
|
|
306
|
+
pss->config = UA_Server_getConfig(pss->server);
|
|
307
|
+
pss->default_ns = 1;
|
|
308
|
+
|
|
309
|
+
UA_ServerConfig_setDefault(pss->config);
|
|
310
|
+
|
|
311
|
+
return Data_Wrap_Struct(self, NULL, server_free, pss);
|
|
312
|
+
} //}}}
|
|
313
|
+
/* ++ */ //}}}
|
|
314
|
+
static VALUE server_init(VALUE self) { //{{{
|
|
315
|
+
server_struct *pss;
|
|
316
|
+
|
|
317
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
318
|
+
|
|
319
|
+
UA_StatusCode retval = UA_Server_run_startup(pss->server);
|
|
320
|
+
if (retval != UA_STATUSCODE_GOOD)
|
|
321
|
+
rb_raise(rb_eRuntimeError, "Server could not be started.");
|
|
322
|
+
|
|
323
|
+
return self;
|
|
324
|
+
} //}}}
|
|
325
|
+
static VALUE server_run(VALUE self) { //{{{
|
|
326
|
+
server_struct *pss;
|
|
327
|
+
|
|
328
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
329
|
+
|
|
330
|
+
UA_UInt16 timeout = UA_Server_run_iterate(pss->server, false);
|
|
331
|
+
|
|
332
|
+
return rb_float_new(timeout/1000.0);
|
|
333
|
+
} //}}}
|
|
334
|
+
static VALUE server_add_namespace(VALUE self, VALUE name) { //{{{
|
|
335
|
+
server_struct *pss;
|
|
336
|
+
|
|
337
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
338
|
+
|
|
339
|
+
VALUE str;
|
|
340
|
+
str = rb_obj_as_string(name);
|
|
341
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
342
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
343
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
344
|
+
|
|
345
|
+
pss->default_ns = UA_Server_addNamespace(pss->server, nstr);
|
|
346
|
+
return self;
|
|
347
|
+
} //}}}
|
|
348
|
+
static VALUE server_types(VALUE self) { //{{{
|
|
349
|
+
server_struct *pss;
|
|
350
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
351
|
+
return node_alloc(cTypesTopNode, pss, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE));
|
|
352
|
+
} //}}}
|
|
353
|
+
static VALUE server_objects(VALUE self) { //{{{
|
|
354
|
+
server_struct *pss;
|
|
355
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
356
|
+
return node_alloc(cObjectsNode, pss, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER));
|
|
357
|
+
} //}}}
|
|
358
|
+
|
|
359
|
+
void Init_server(void) {
|
|
360
|
+
mOPCUA = rb_define_module("OPCUA");
|
|
361
|
+
rb_define_const(mOPCUA, "MANDATORY", INT2NUM(UA_NS0ID_MODELLINGRULE_MANDATORY));
|
|
362
|
+
rb_define_const(mOPCUA, "MANDATORYPLACEHOLDER", INT2NUM(UA_NS0ID_MODELLINGRULE_MANDATORYPLACEHOLDER));
|
|
363
|
+
rb_define_const(mOPCUA, "OPTIONAL", INT2NUM(UA_NS0ID_MODELLINGRULE_OPTIONAL));
|
|
364
|
+
rb_define_const(mOPCUA, "OPTIONALPLACEHOLDER", INT2NUM(UA_NS0ID_MODELLINGRULE_OPTIONALPLACEHOLDER));
|
|
365
|
+
|
|
366
|
+
cServer = rb_define_class_under(mOPCUA, "Server", rb_cObject);
|
|
367
|
+
cObjectsNode = rb_define_class_under(mOPCUA, "cObjectsNode", rb_cObject);
|
|
368
|
+
cTypesTopNode = rb_define_class_under(mOPCUA, "cTypesTopNode", rb_cObject);
|
|
369
|
+
cTypesSubNode = rb_define_class_under(mOPCUA, "cTypesSubNode", rb_cObject);
|
|
370
|
+
cLeafNode = rb_define_class_under(mOPCUA, "cLeafNode", rb_cObject);
|
|
371
|
+
|
|
372
|
+
rb_define_alloc_func(cServer, server_alloc);
|
|
373
|
+
rb_define_method(cServer, "initialize", server_init, 0);
|
|
374
|
+
rb_define_method(cServer, "run", server_run, 0);
|
|
375
|
+
rb_define_method(cServer, "add_namespace", server_add_namespace, 1);
|
|
376
|
+
rb_define_method(cServer, "types", server_types, 0);
|
|
377
|
+
rb_define_method(cServer, "objects", server_objects, 0);
|
|
378
|
+
|
|
379
|
+
rb_define_method(cTypesTopNode, "add_object_type", node_add_object_type, 1);
|
|
380
|
+
rb_define_method(cTypesTopNode, "folder", node_type_folder, 0);
|
|
381
|
+
rb_define_method(cTypesSubNode, "add_object_type", node_add_object_type, 1);
|
|
382
|
+
rb_define_method(cTypesSubNode, "add_variable", node_add_variable, -1);
|
|
383
|
+
rb_define_method(cTypesSubNode, "add_object", node_add_object, -1);
|
|
384
|
+
rb_define_method(cTypesSubNode, "id", node_id, 0);
|
|
385
|
+
|
|
386
|
+
rb_define_method(cObjectsNode, "instantiate", node_add_object_without, 2);
|
|
387
|
+
rb_define_method(cObjectsNode, "add_variable", node_add_variable_without, 1);
|
|
388
|
+
rb_define_method(cObjectsNode, "find", node_find, 1);
|
|
389
|
+
rb_define_method(cObjectsNode, "value", node_value, 0);
|
|
390
|
+
rb_define_method(cObjectsNode, "value=", node_value_set, 1);
|
|
391
|
+
rb_define_method(cObjectsNode, "id", node_id, 0);
|
|
392
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#include <ruby.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <open62541.h>
|
|
4
|
+
|
|
5
|
+
typedef struct server_struct {
|
|
6
|
+
UA_ServerConfig *config;
|
|
7
|
+
UA_Server *server;
|
|
8
|
+
UA_UInt16 default_ns;
|
|
9
|
+
} server_struct;
|
|
10
|
+
|
|
11
|
+
typedef struct node_struct {
|
|
12
|
+
server_struct *server;
|
|
13
|
+
UA_NodeId id;
|
|
14
|
+
} node_struct;
|
data/lib/opcua/client.rb
CHANGED
data/lib/opcua/server.rb
CHANGED
data/opcua.gemspec
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "opcua"
|
|
3
|
-
s.version = "0.
|
|
3
|
+
s.version = "0.7"
|
|
4
4
|
s.platform = Gem::Platform::RUBY
|
|
5
5
|
s.license = "LGPL-3.0"
|
|
6
6
|
s.summary = "Preliminary release of opcua (open62541) ruby bindings. C performance, Ruby elegance, simplicity, and productivity."
|
|
7
7
|
|
|
8
8
|
s.description = "see https://github.com/etm/opcua-smart"
|
|
9
9
|
|
|
10
|
-
s.files = Dir['{example/**/*,tools/**/*,lib
|
|
10
|
+
s.files = Dir['{example/**/*,tools/**/*,lib/**/*.rb,ext/**/*.c,ext/**/*.h,cert/*.h,contrib/logo*}'] + %w(COPYING Rakefile opcua.gemspec README.md)
|
|
11
11
|
s.extensions = Dir["ext/**/extconf.rb"]
|
|
12
12
|
s.require_path = 'lib'
|
|
13
13
|
s.extra_rdoc_files = ['README.md']
|
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
|
20
20
|
s.email = 'juergen.mangler@gmail.com'
|
|
21
21
|
s.homepage = 'https://github.com/etm/opcua-smart'
|
|
22
22
|
|
|
23
|
-
s.add_runtime_dependency 'daemonite', '~> 0'
|
|
23
|
+
s.add_runtime_dependency 'daemonite', '~> 0', '>= 0.5'
|
|
24
24
|
s.add_development_dependency 'rake', '~> 12'
|
|
25
25
|
s.add_development_dependency 'rake-compiler', '~> 1.0'
|
|
26
26
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opcua
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.7'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Juergen eTM Mangler
|
|
@@ -18,6 +18,9 @@ dependencies:
|
|
|
18
18
|
- - "~>"
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
20
|
version: '0'
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: '0.5'
|
|
21
24
|
type: :runtime
|
|
22
25
|
prerelease: false
|
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -25,6 +28,9 @@ dependencies:
|
|
|
25
28
|
- - "~>"
|
|
26
29
|
- !ruby/object:Gem::Version
|
|
27
30
|
version: '0'
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.5'
|
|
28
34
|
- !ruby/object:Gem::Dependency
|
|
29
35
|
name: rake
|
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,16 +71,20 @@ files:
|
|
|
65
71
|
- COPYING
|
|
66
72
|
- README.md
|
|
67
73
|
- Rakefile
|
|
74
|
+
- cert/cert.h
|
|
75
|
+
- cert/cert_key.h
|
|
68
76
|
- example/client.rb
|
|
69
77
|
- example/kelch.KMT
|
|
70
78
|
- example/server.rb
|
|
71
79
|
- example/test.rb
|
|
80
|
+
- ext/opcua/client/client.c
|
|
81
|
+
- ext/opcua/client/client.h
|
|
72
82
|
- ext/opcua/client/extconf.rb
|
|
73
83
|
- ext/opcua/server/extconf.rb
|
|
84
|
+
- ext/opcua/server/server.c
|
|
85
|
+
- ext/opcua/server/server.h
|
|
74
86
|
- lib/opcua/client.rb
|
|
75
|
-
- lib/opcua/client.so
|
|
76
87
|
- lib/opcua/server.rb
|
|
77
|
-
- lib/opcua/server.so
|
|
78
88
|
- opcua.gemspec
|
|
79
89
|
homepage: https://github.com/etm/opcua-smart
|
|
80
90
|
licenses:
|
data/lib/opcua/client.so
DELETED
|
Binary file
|
data/lib/opcua/server.so
DELETED
|
Binary file
|