Repository navigation
Real Array Datatypes
REALARRAY and LREALARRAY share the RealArray template. They behave identically to the numeric array types with one important distinction: because floating-point values cannot be reliably compared to zero using ==, all empty-slot checks use a tolerance threshold of 1e-9. Any value with abs(v) < 1e-9 is considered an empty slot.
| Type | Accessor | Element type | Precision |
|---|---|---|---|
REALARRAY |
actions.realarray |
REAL |
32-bit IEEE 754 single |
LREALARRAY |
actions.lrealarray |
LREAL |
64-bit IEEE 754 double |
from ethernetip_emulator.server.device import actions
# Tag definitions
("O_Temperatures", actions.type.REALARRAY([0.0, 0.0, 0.0, 0.0]))
("O_Pressures", actions.type.LREALARRAY([0.0, 0.0, 0.0, 0.0]))Empty slots are identified by the _is_zero check: abs(v) < 1e-9. This means:
-
0.0is an empty slot ✓ -
0.0000000001is not empty (exceeds tolerance) -
-0.0000000001is not empty (exceeds tolerance)
This is intentional — it avoids false positives from floating-point arithmetic rounding. If you store legitimate values very close to zero, be aware they may be treated as empty slots by list operations.
Returns the full array or a sub-range as a list[float].
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str |
— | Tag name. |
key |
slice | None |
full array | Sub-range to read. |
actions.realarray.get_val("O_Temperatures") # → [23.5, 0.0, 18.1, 0.0]
actions.realarray.get_val("O_Temperatures", slice(0, 2)) # → [23.5, 0.0]Writes a list of floats to the array or a sub-range.
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str |
— | Tag name. |
value |
list[float] |
— | Values to write. |
key |
slice | None |
full array | Sub-range to write. |
actions.realarray.set_val("O_Temperatures", [23.5, 0.0, 18.1, 0.0])
actions.realarray.set_val("O_Temperatures", [99.9], slice(2, 3)) # write only index 2Returns the total number of elements, or None if the tag does not exist.
actions.realarray.size("O_Temperatures") # → 4Returns the number of non-zero elements (using the 1e-9 tolerance).
# [23.5, 0.0, 18.1, 0.0]
actions.realarray.count("O_Temperatures") # → 2Returns True if every element is non-zero (outside tolerance).
actions.realarray.is_full("O_Temperatures") # → FalseReturns True if every element is within 1e-9 of zero.
actions.realarray.is_empty("O_Temperatures") # → FalseReturns the zero-based index of the first element within 1e-9 of value, or None if not found.
# [23.5, 0.0, 18.1, 0.0]
actions.realarray.find("O_Temperatures", 18.1) # → 2
actions.realarray.find("O_Temperatures", 99.9) # → NoneWrites value into the first slot within tolerance of 0.0 (scanning left to right). Returns True on success, False if no empty slot is available.
# [23.5, 0.0, 18.1, 0.0]
actions.realarray.append("O_Temperatures", 21.0) # → True
# [23.5, 21.0, 18.1, 0.0]Writes value into the last slot within tolerance of 0.0 (scanning right to left). Returns True on success, False if no empty slot is available.
# [23.5, 21.0, 18.1, 0.0]
actions.realarray.prepend("O_Temperatures", 5.5) # → True
# [23.5, 21.0, 18.1, 5.5]Clears (sets to 0.0) the last non-zero element and returns its value. Returns None if all elements are within tolerance of zero.
# [23.5, 21.0, 18.1, 5.5]
actions.realarray.pop("O_Temperatures") # → 5.5
# [23.5, 21.0, 18.1, 0.0]Inserts value at index, shifting all subsequent elements one position to the right. The last element is lost if the array is full. Returns False if there is no room (last element is non-zero), True on success.
# [23.5, 21.0, 18.1, 0.0]
actions.realarray.insert("O_Temperatures", 1, 99.9) # → True
# [23.5, 99.9, 21.0, 18.1]Removes the element at index, shifting subsequent elements one position to the left. The last element is set to 0.0. Returns the removed value, or None if the element at index was within tolerance of zero.
# [23.5, 99.9, 21.0, 18.1]
actions.realarray.remove("O_Temperatures", 1) # → 99.9
# [23.5, 21.0, 18.1, 0.0]Sets all elements (or a sub-range) to 0.0.
actions.realarray.clear("O_Temperatures")
# [0.0, 0.0, 0.0, 0.0]on_change defaults to the full array slice when no key is provided.
# Fires when any element in the array is written
@actions.realarray.on_change("O_Temperatures")
def any_changed(attr, key, value):
print(f"Temperatures updated: {actions.realarray.get_val('O_Temperatures')}")
# Fires only when index 0 is written
@actions.realarray.on_change("O_Temperatures", key=slice(0, 1))
def sensor_0_changed(attr, key, value):
print(f"Sensor 0 reading: {value[0]:.2f}")See Working with Actions for full documentation on key and defer.
| Method | Description |
|---|---|
get_val(name, key?) |
Read the full array or a sub-range as list[float]
|
set_val(name, value, key?) |
Write a list of floats to the array or a sub-range |
size(name) |
Return the total number of elements |
count(name, key?) |
Count non-zero elements (tolerance: 1e-9) |
is_full(name, key?) |
True if all elements are non-zero |
is_empty(name, key?) |
True if all elements are within 1e-9 of zero |
find(name, value, key?) |
Return the index of the first element within 1e-9 of value
|
append(name, value, key?) |
Write into the first zero slot |
prepend(name, value, key?) |
Write into the last zero slot |
pop(name, key?) |
Clear and return the last non-zero element |
insert(name, index, value, key?) |
Insert at index, shifting right |
remove(name, index, key?) |
Remove at index, shifting left |
clear(name, key?) |
Set all elements to 0.0
|
on_change(name, callback?, key?, defer?) |
Register a change listener |