0
# Value System
1
2
Universal value abstraction providing type-safe access to PLC data with automatic conversion in Apache PLC4X Java API.
3
4
## Capabilities
5
6
### PlcValue
7
8
Universal value interface providing comprehensive type system for PLC data.
9
10
```java { .api }
11
/**
12
* Universal value interface for type-safe access to PLC data
13
*/
14
public interface PlcValue {
15
/**
16
* Get the PLC value type
17
* @return PlcValueType enum indicating the data type
18
*/
19
PlcValueType getPlcValueType();
20
21
/**
22
* Get the raw object representation
23
* @return Object containing the raw value
24
*/
25
Object getObject();
26
27
// Type checking methods
28
/**
29
* Check if this is a simple (non-complex) value type
30
* @return true if simple type (not struct or list)
31
*/
32
boolean isSimple();
33
34
/**
35
* Check if this value type supports null values
36
* @return true if nullable
37
*/
38
boolean isNullable();
39
40
/**
41
* Check if this value is null
42
* @return true if null
43
*/
44
boolean isNull();
45
46
/**
47
* Check if value is of specific Java type
48
* @param clazz Java class to check against
49
* @return true if value is of specified type
50
*/
51
boolean is(Class<?> clazz);
52
53
/**
54
* Check if value can be converted to specific Java type
55
* @param clazz Java class to check conversion to
56
* @return true if convertible
57
*/
58
boolean isConvertibleTo(Class<?> clazz);
59
60
/**
61
* Get value as specific Java type with conversion
62
* @param clazz Target Java class
63
* @return Value converted to specified type
64
* @throws PlcIncompatibleDatatypeException if conversion fails
65
*/
66
<T> T get(Class<T> clazz);
67
68
// Boolean type methods
69
/**
70
* Check if value is boolean type
71
* @return true if boolean
72
*/
73
boolean isBoolean();
74
75
/**
76
* Get boolean value
77
* @return boolean value
78
* @throws PlcIncompatibleDatatypeException if not convertible
79
*/
80
boolean getBoolean();
81
82
// Byte type methods
83
/**
84
* Check if value is byte type
85
* @return true if byte
86
*/
87
boolean isByte();
88
89
/**
90
* Get byte value
91
* @return byte value
92
* @throws PlcIncompatibleDatatypeException if not convertible
93
*/
94
byte getByte();
95
96
// Short type methods
97
/**
98
* Check if value is short type
99
* @return true if short
100
*/
101
boolean isShort();
102
103
/**
104
* Get short value
105
* @return short value
106
* @throws PlcIncompatibleDatatypeException if not convertible
107
*/
108
short getShort();
109
110
// Integer type methods
111
/**
112
* Check if value is integer type
113
* @return true if integer
114
*/
115
boolean isInteger();
116
117
/**
118
* Get integer value
119
* @return integer value
120
* @throws PlcIncompatibleDatatypeException if not convertible
121
*/
122
int getInteger();
123
124
// Long type methods
125
/**
126
* Check if value is long type
127
* @return true if long
128
*/
129
boolean isLong();
130
131
/**
132
* Get long value
133
* @return long value
134
* @throws PlcIncompatibleDatatypeException if not convertible
135
*/
136
long getLong();
137
138
// Float type methods
139
/**
140
* Check if value is float type
141
* @return true if float
142
*/
143
boolean isFloat();
144
145
/**
146
* Get float value
147
* @return float value
148
* @throws PlcIncompatibleDatatypeException if not convertible
149
*/
150
float getFloat();
151
152
// Double type methods
153
/**
154
* Check if value is double type
155
* @return true if double
156
*/
157
boolean isDouble();
158
159
/**
160
* Get double value
161
* @return double value
162
* @throws PlcIncompatibleDatatypeException if not convertible
163
*/
164
double getDouble();
165
166
// String type methods
167
/**
168
* Check if value is string type
169
* @return true if string
170
*/
171
boolean isString();
172
173
/**
174
* Get string value
175
* @return string value
176
* @throws PlcIncompatibleDatatypeException if not convertible
177
*/
178
String getString();
179
180
// Time type methods
181
/**
182
* Check if value is time type
183
* @return true if time
184
*/
185
boolean isTime();
186
187
/**
188
* Get time value
189
* @return LocalTime value
190
* @throws PlcIncompatibleDatatypeException if not convertible
191
*/
192
LocalTime getTime();
193
194
// Date type methods
195
/**
196
* Check if value is date type
197
* @return true if date
198
*/
199
boolean isDate();
200
201
/**
202
* Get date value
203
* @return LocalDate value
204
* @throws PlcIncompatibleDatatypeException if not convertible
205
*/
206
LocalDate getDate();
207
208
// DateTime type methods
209
/**
210
* Check if value is datetime type
211
* @return true if datetime
212
*/
213
boolean isDateTime();
214
215
/**
216
* Get datetime value
217
* @return LocalDateTime value
218
* @throws PlcIncompatibleDatatypeException if not convertible
219
*/
220
LocalDateTime getDateTime();
221
222
// Duration type methods
223
/**
224
* Check if value is duration type
225
* @return true if duration
226
*/
227
boolean isDuration();
228
229
/**
230
* Get duration value
231
* @return Duration value
232
* @throws PlcIncompatibleDatatypeException if not convertible
233
*/
234
Duration getDuration();
235
236
// BigInteger type methods
237
/**
238
* Check if value is BigInteger type
239
* @return true if BigInteger
240
*/
241
boolean isBigInteger();
242
243
/**
244
* Get BigInteger value
245
* @return BigInteger value
246
* @throws PlcIncompatibleDatatypeException if not convertible
247
*/
248
BigInteger getBigInteger();
249
250
// BigDecimal type methods
251
/**
252
* Check if value is BigDecimal type
253
* @return true if BigDecimal
254
*/
255
boolean isBigDecimal();
256
257
/**
258
* Get BigDecimal value
259
* @return BigDecimal value
260
* @throws PlcIncompatibleDatatypeException if not convertible
261
*/
262
BigDecimal getBigDecimal();
263
264
// Raw data methods
265
/**
266
* Get raw byte array representation
267
* @return byte array containing raw data
268
*/
269
byte[] getRaw();
270
271
// List/Array methods
272
/**
273
* Check if value is a list/array type
274
* @return true if list
275
*/
276
boolean isList();
277
278
/**
279
* Get length of list/array
280
* @return number of elements
281
*/
282
int getLength();
283
284
/**
285
* Get element at specific index
286
* @param index Array index
287
* @return PlcValue at specified index
288
*/
289
PlcValue getIndex(int index);
290
291
/**
292
* Get all list elements
293
* @return List of PlcValue elements
294
*/
295
List<? extends PlcValue> getList();
296
297
// Struct methods
298
/**
299
* Check if value is a struct type
300
* @return true if struct
301
*/
302
boolean isStruct();
303
304
/**
305
* Get struct field names
306
* @return Set of field names
307
*/
308
Set<String> getKeys();
309
310
/**
311
* Check if struct has specific field
312
* @param key Field name
313
* @return true if field exists
314
*/
315
boolean hasKey(String key);
316
317
/**
318
* Get struct field value
319
* @param key Field name
320
* @return PlcValue for the field
321
*/
322
PlcValue getValue(String key);
323
324
/**
325
* Get struct as Map
326
* @return Map of field names to PlcValue
327
*/
328
Map<String, ? extends PlcValue> getStruct();
329
330
// Metadata methods
331
/**
332
* Get available metadata names
333
* @return Set of metadata names
334
*/
335
Set<String> getMetaDataNames();
336
337
/**
338
* Check if specific metadata exists
339
* @param key Metadata key
340
* @return true if metadata exists
341
*/
342
boolean hasMetaData(String key);
343
344
/**
345
* Get metadata value
346
* @param key Metadata key
347
* @return PlcValue containing metadata
348
*/
349
PlcValue getMetaData(String key);
350
}
351
```
352
353
**Usage Examples:**
354
355
```java
356
import org.apache.plc4x.java.DefaultPlcDriverManager;
357
import org.apache.plc4x.java.api.PlcConnection;
358
import org.apache.plc4x.java.api.messages.PlcReadRequest;
359
import org.apache.plc4x.java.api.messages.PlcReadResponse;
360
import org.apache.plc4x.java.api.value.PlcValue;
361
import org.apache.plc4x.java.api.types.PlcValueType;
362
363
// Basic value type checking and conversion
364
PlcDriverManager driverManager = new DefaultPlcDriverManager();
365
try (PlcConnection connection = driverManager.getConnection("modbus-tcp://192.168.1.100:502")) {
366
connection.connect();
367
368
PlcReadRequest readRequest = connection.readRequestBuilder()
369
.addTagAddress("temperature", "holding-register:1")
370
.addTagAddress("status", "coil:1")
371
.addTagAddress("device_name", "holding-register:100[10]")
372
.build();
373
374
PlcReadResponse response = readRequest.execute().get();
375
376
// Temperature - numeric value
377
PlcValue tempValue = response.getPlcValue("temperature");
378
System.out.println("Value type: " + tempValue.getPlcValueType());
379
380
// Check type and convert appropriately
381
if (tempValue.isFloat()) {
382
float temperature = tempValue.getFloat();
383
System.out.println("Temperature: " + temperature + "°C");
384
} else if (tempValue.isInteger()) {
385
int temperature = tempValue.getInteger();
386
System.out.println("Temperature: " + temperature + "°C");
387
} else if (tempValue.isConvertibleTo(Double.class)) {
388
double temperature = tempValue.get(Double.class);
389
System.out.println("Temperature: " + temperature + "°C");
390
}
391
392
// Status - boolean value
393
PlcValue statusValue = response.getPlcValue("status");
394
if (statusValue.isBoolean()) {
395
boolean status = statusValue.getBoolean();
396
System.out.println("Status: " + (status ? "ON" : "OFF"));
397
}
398
399
// Device name - string or array conversion
400
PlcValue nameValue = response.getPlcValue("device_name");
401
if (nameValue.isString()) {
402
String name = nameValue.getString();
403
System.out.println("Device: " + name);
404
} else if (nameValue.isList()) {
405
// Convert array of registers to string
406
StringBuilder name = new StringBuilder();
407
for (int i = 0; i < nameValue.getLength(); i++) {
408
PlcValue element = nameValue.getIndex(i);
409
if (element.isInteger()) {
410
int charValue = element.getInteger();
411
if (charValue != 0) { // Skip null terminators
412
name.append((char) charValue);
413
}
414
}
415
}
416
System.out.println("Device: " + name.toString());
417
}
418
}
419
420
// Array/List processing
421
try (PlcConnection connection = driverManager.getConnection("s7://192.168.1.200/0/1")) {
422
connection.connect();
423
424
PlcReadRequest readRequest = connection.readRequestBuilder()
425
.addTagAddress("sensor_array", "DB1.DBD0:REAL[10]")
426
.build();
427
428
PlcReadResponse response = readRequest.execute().get();
429
PlcValue arrayValue = response.getPlcValue("sensor_array");
430
431
if (arrayValue.isList()) {
432
System.out.println("Array length: " + arrayValue.getLength());
433
434
// Process each element
435
for (int i = 0; i < arrayValue.getLength(); i++) {
436
PlcValue element = arrayValue.getIndex(i);
437
if (element.isFloat()) {
438
float value = element.getFloat();
439
System.out.println("Sensor[" + i + "]: " + value);
440
}
441
}
442
443
// Get as Java list
444
List<? extends PlcValue> sensorList = arrayValue.getList();
445
double average = sensorList.stream()
446
.filter(PlcValue::isFloat)
447
.mapToDouble(PlcValue::getFloat)
448
.average()
449
.orElse(0.0);
450
System.out.println("Average sensor value: " + average);
451
}
452
}
453
454
// Struct/Complex data processing
455
try (PlcConnection connection = driverManager.getConnection("s7://192.168.1.200/0/1")) {
456
connection.connect();
457
458
PlcReadRequest readRequest = connection.readRequestBuilder()
459
.addTagAddress("recipe_data", "DB10:STRUCT")
460
.build();
461
462
PlcReadResponse response = readRequest.execute().get();
463
PlcValue structValue = response.getPlcValue("recipe_data");
464
465
if (structValue.isStruct()) {
466
System.out.println("Struct fields: " + structValue.getKeys());
467
468
// Access individual fields
469
if (structValue.hasKey("temperature")) {
470
PlcValue tempField = structValue.getValue("temperature");
471
if (tempField.isFloat()) {
472
float temperature = tempField.getFloat();
473
System.out.println("Recipe temperature: " + temperature);
474
}
475
}
476
477
if (structValue.hasKey("duration")) {
478
PlcValue durationField = structValue.getValue("duration");
479
if (durationField.isInteger()) {
480
int duration = durationField.getInteger();
481
System.out.println("Recipe duration: " + duration + " seconds");
482
}
483
}
484
485
// Get as map for bulk processing
486
Map<String, ? extends PlcValue> structMap = structValue.getStruct();
487
structMap.forEach((fieldName, fieldValue) -> {
488
System.out.println(fieldName + ": " + fieldValue.getObject());
489
});
490
}
491
}
492
493
// Type conversion and validation
494
try (PlcConnection connection = driverManager.getConnection("modbus-tcp://192.168.1.100:502")) {
495
connection.connect();
496
497
PlcReadRequest readRequest = connection.readRequestBuilder()
498
.addTagAddress("mixed_data", "holding-register:1")
499
.build();
500
501
PlcReadResponse response = readRequest.execute().get();
502
PlcValue value = response.getPlcValue("mixed_data");
503
504
// Safe type conversion with validation
505
if (value.isConvertibleTo(String.class)) {
506
String stringValue = value.get(String.class);
507
System.out.println("As string: " + stringValue);
508
}
509
510
if (value.isConvertibleTo(Integer.class)) {
511
Integer intValue = value.get(Integer.class);
512
System.out.println("As integer: " + intValue);
513
}
514
515
if (value.isConvertibleTo(BigDecimal.class)) {
516
BigDecimal decimalValue = value.get(BigDecimal.class);
517
System.out.println("As BigDecimal: " + decimalValue);
518
}
519
520
// Raw data access
521
byte[] rawData = value.getRaw();
522
System.out.println("Raw bytes: " + Arrays.toString(rawData));
523
}
524
525
// Time/Date handling
526
try (PlcConnection connection = driverManager.getConnection("s7://192.168.1.200/0/1")) {
527
connection.connect();
528
529
PlcReadRequest readRequest = connection.readRequestBuilder()
530
.addTagAddress("timestamp", "DB20.DBD0:DATE_AND_TIME")
531
.addTagAddress("duration", "DB20.DBD8:TIME")
532
.build();
533
534
PlcReadResponse response = readRequest.execute().get();
535
536
// DateTime handling
537
PlcValue timestampValue = response.getPlcValue("timestamp");
538
if (timestampValue.isDateTime()) {
539
LocalDateTime timestamp = timestampValue.getDateTime();
540
System.out.println("Timestamp: " + timestamp);
541
}
542
543
// Duration handling
544
PlcValue durationValue = response.getPlcValue("duration");
545
if (durationValue.isDuration()) {
546
Duration duration = durationValue.getDuration();
547
System.out.println("Duration: " + duration.toSeconds() + " seconds");
548
}
549
}
550
551
// Metadata access
552
try (PlcConnection connection = driverManager.getConnection("modbus-tcp://192.168.1.100:502")) {
553
connection.connect();
554
555
PlcReadRequest readRequest = connection.readRequestBuilder()
556
.addTagAddress("data", "holding-register:1")
557
.build();
558
559
PlcReadResponse response = readRequest.execute().get();
560
PlcValue value = response.getPlcValue("data");
561
562
// Check for metadata
563
if (!value.getMetaDataNames().isEmpty()) {
564
System.out.println("Available metadata: " + value.getMetaDataNames());
565
566
for (String metaKey : value.getMetaDataNames()) {
567
PlcValue metaValue = value.getMetaData(metaKey);
568
System.out.println("Metadata " + metaKey + ": " + metaValue.getObject());
569
}
570
}
571
}
572
```
573
574
## Types
575
576
### PlcValueType Enum
577
578
```java { .api }
579
/**
580
* Comprehensive enumeration of PLC value types
581
*/
582
public enum PlcValueType {
583
// Null type
584
NULL,
585
586
// Boolean types
587
BOOL,
588
589
// Bit string types
590
BYTE, WORD, DWORD, LWORD,
591
592
// Unsigned integer types
593
USINT, // Unsigned 8-bit integer
594
UINT, // Unsigned 16-bit integer
595
UDINT, // Unsigned 32-bit integer
596
ULINT, // Unsigned 64-bit integer
597
598
// Signed integer types
599
SINT, // Signed 8-bit integer
600
INT, // Signed 16-bit integer
601
DINT, // Signed 32-bit integer
602
LINT, // Signed 64-bit integer
603
604
// Floating point types
605
REAL, // 32-bit floating point
606
LREAL, // 64-bit floating point
607
608
// Character types
609
CHAR, // Single character
610
WCHAR, // Wide character
611
612
// String types
613
STRING, // Character string
614
WSTRING, // Wide character string
615
616
// Time types
617
TIME, // Time duration
618
LTIME, // Long time duration
619
DATE, // Date
620
LDATE, // Long date
621
TIME_OF_DAY, // Time of day
622
LTIME_OF_DAY, // Long time of day
623
DATE_AND_TIME, // Date and time
624
DATE_AND_LTIME, // Date and long time
625
LDATE_AND_TIME, // Long date and time
626
627
// Complex types
628
Struct, // Structure/record type
629
List, // Array/list type
630
631
// Raw data
632
RAW_BYTE_ARRAY; // Raw byte array
633
634
/**
635
* Get numeric value for the type
636
* @return short value representing the type
637
*/
638
public short getValue();
639
640
/**
641
* Get the default Java type for this PLC type
642
* @return Class representing the default Java mapping
643
*/
644
public Class<?> getDefaultJavaType();
645
}
646
```
647
648
### Type Conversion Matrix
649
650
| PlcValueType | Java Types | Description |
651
|--------------|------------|-------------|
652
| `BOOL` | `boolean`, `Boolean` | Boolean values |
653
| `BYTE`, `SINT` | `byte`, `Byte` | 8-bit signed integers |
654
| `WORD`, `INT` | `short`, `Short` | 16-bit signed integers |
655
| `DWORD`, `DINT` | `int`, `Integer` | 32-bit signed integers |
656
| `LWORD`, `LINT` | `long`, `Long` | 64-bit signed integers |
657
| `USINT` | `short`, `int` | 8-bit unsigned integers |
658
| `UINT` | `int`, `Integer` | 16-bit unsigned integers |
659
| `UDINT` | `long`, `Long` | 32-bit unsigned integers |
660
| `ULINT` | `BigInteger` | 64-bit unsigned integers |
661
| `REAL` | `float`, `Float` | 32-bit floating point |
662
| `LREAL` | `double`, `Double` | 64-bit floating point |
663
| `STRING`, `WSTRING` | `String` | Character strings |
664
| `TIME`, `LTIME` | `Duration` | Time durations |
665
| `DATE`, `LDATE` | `LocalDate` | Date values |
666
| `TIME_OF_DAY` | `LocalTime` | Time of day |
667
| `DATE_AND_TIME` | `LocalDateTime` | Date and time |
668
| `List` | `List<PlcValue>` | Arrays/lists |
669
| `Struct` | `Map<String, PlcValue>` | Structures/records |