TapHome

Data types

Data types of the TapHome script language: numbers, text, structured and enum types, collections, the .Type property, type promotion in arithmetic, and how Null and NaN behave.

Scalar types

Every value in a script carries a concrete type. The type names below are used in typed declarations (see Local variables), and the .Type property returns them.

TypeValuesNotes
boolTRUE, FALSEAny non-zero number converts to TRUE, zero to FALSE.
int8, uint8, int16, uint16, int, uint, int64, uint64Whole numbers of 8, 16, 32 and 64 bitsint and uint are the 32-bit types. uint8 is the byte of byte collections.
float, doubleFloating point numbersNumber literals and most arithmetic give a double.
charOne character, 'A'Takes part in arithmetic as its character code.
stringText, "abc"+ with a string on either side joins text.

Int32 x := 4; fails with Unknown variable or constant 'Int32'. Names such as Int32 and UInt32 exist only among the Modbus data types of MODBUSR and MODBUSW.

Structured types

Structured types hold several values, available as properties:

TypeHoldsProperties
datetimeDate and time with a kind (Local, Utc, Unspecified)See Date and time
timespanTime intervalDays, Hours, Minutes, Seconds, Milliseconds, TotalDays, TotalHours, TotalMinutes, TotalSeconds, TotalMilliseconds (read-only)
httprequestPrepared HTTP request from HTTPREQUESTPath, Method, Body, Headers (read and write)
httpresponseAnswer of SENDHTTPREQUESTContent, Headers, IsSuccess, StatusCode, ReasonPhrase (read-only)
receivedmessageIncoming message RECEIVEDMSG of a listener scriptProtocol, Payload, Length, Topic, ContentType, PayloadFormat, ClientId, Expiry, Dup (read-only)
blobRaw bytes, for example RECEIVEDMSG.PAYLOADLength (read-only)
rgbcolor, hsvcolorColours, see ColoursRed, Green, Blue and Hue, Saturation, Value (read and write)
groupvalueValue of a device groupCalculated, Values (read-only)
currentvalueinfo, historyvaluesParts of a Value info variableSee Value info

Enum types

An enum type is a fixed set of named values that some functions take as a parameter:

TypeValuesUsed by
ModbusRegisterTypeC, H, D, AModbus functions
ModbusDataTypeInt16, Uint16, Int32, UInt32, Float, Bool, String, Int64, UInt64, Double and their byte-order variants, see Modbus data typesModbus functions, PACKVALUE, UNPACKVALUE
LinearTypeDEFAULT, BOUNDS, STRICT, INFINITELINEAR
DateTimeKindLocal, Utc, UnspecifiedNOW, DATETIME
DayOfWeekMonday … Sundaydatetime properties
CompareOptionsNone, IgnoreCase, IgnoreNonSpace, IgnoreSymbols, IgnoreKanaType, IgnoreWidth, OrdinalIgnoreCase, StringSort, OrdinalCOMPARE

An enum value is written bare (Utc) or with its type (DateTimeKind.Utc). Enum types also work as declaration keywords:

DateTimeKind kind := Utc;
VAR t := NOW(kind);

Collections

collection<T> is a list of values of one element type T.

collection<uint16> registers := UINT16COLLECTION(4);
collection<string> names := {"a", "b", "c"};
collection<uint8> data := BYTECOLLECTION("0A0B0C");
LENGTH(names);
# Result: 3
  • The element type comes from the declaration, otherwise from the first element that is not Null. {Null} alone fails with Unable to determine collection type.
  • Nested collections are not supported: Collection<Collection<>> is not supported.
  • Collections are reference values. APPEND, INSERT, REMOVEAT, SETAT and REPLACE change the collection in place and return the same collection.
  • BYTECOLLECTION, UINT16COLLECTION and BOOLCOLLECTION create at most 2048 elements; each form reports a larger count with its own message (see Run-time errors).
  • LENGTH(c) or c.Length returns the number of elements.

Available — typed collections from Core 2022.2; UINT16COLLECTION and BOOLCOLLECTION from Core 2026.1, build 39001.

The .Type property

Every value has the read-only property .Type, which returns the name of its type as text. For an enum value it is the enum type, for example "DateTimeKind".

VAR x := 5.5;
x.Type;
# Result: "Double"
VAR c := BYTECOLLECTION("0A0B");
c.Type;
# Result: "Collection<UInt8>"

Properties can be read only from a named variable. AVG('a', 'c').Type fails with Unexpected character '.'; store the value in a variable first.

Type conversion rules

In arithmetic the first rule that matches the two operands decides the type of the result:

  1. Either operand is double (or a group value): double.
  2. Either operand is float: float.
  3. Either operand is int64: int64.
  4. Either operand is uint64: uint64.
  5. Either operand is uint: uint when the other one is unsigned too, otherwise int64.
  6. Otherwise (smaller integers, bool, char): int.

Division of two integers truncates. A number literal is a double, so dividing by it does not:

int a := 5;
int b := 2;
a / b;
# Result: 2
a / 2;
# Result: 2.5
  • Bitwise operators work on integers; a double operand is converted to int64 first.
  • + with a string on either side joins text: "T=" + 21.5 is "T=21.5".
  • datetime + number adds milliseconds, datetime + timespan adds the interval, and timespan ± timespan works as expected.
  • Dividing by zero stops the script with Division by zero. Guard the divisor with IF.
  • Assigning to a typed variable converts the value to its type, see Local variables.

Null and NaN

NaN is a number whose value is unknown, for example a sensor that was not read yet or a device in error. Null means there is no value at all: a deleted device, or a function that found nothing.

  • Comparing with the literal NaN (x = NaN, x < NaN) is rejected when the script is parsed: Comparison with NaN is always false. Use the IsNaN method to check for NaN value. Use ISNAN.
  • <, >, <= and >= with a Null operand give FALSE. Null = Null, Null <= Null and Null >= Null are TRUE, Null = 5 is FALSE.
  • &, | and ^ with a Null operand give Null; << and >> give Null for a Null value on the left, while a Null shift count stops the script with Cannot cast DataType.Null to number.
  • Arithmetic and logic with Null (Null + 5, !Null) stops the script with Operator '+' not defined for 'Null' and 'Double'. Check the value with ISNULL first.
  • A Null condition of IF counts as FALSE.
  • MIN, MAX, AVG and ORDER skip Null and NaN; the …STRICT variants pass them on. EQUALS(NaN, NaN) is TRUE.
IF(ISNULL(value) OR ISNAN(value), 0, value);
# Result: the value, or 0 when it is missing or unknown