• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

node-opcua / node-opcua / 23974043205

04 Apr 2026 07:17AM UTC coverage: 92.589% (+0.01%) from 92.576%
23974043205

push

github

erossignon
chore: fix Mocha.Suite.settimeout misused

18408 of 21832 branches covered (84.32%)

161708 of 174651 relevant lines covered (92.59%)

461089.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.48
/packages/node-opcua-server/source/validate_filter.ts
1
/**
110✔
2
 * @module node-opcua-server
2✔
3
 */
2✔
4

2✔
5
import type { BaseNode, UAVariable } from "node-opcua-address-space";
2✔
6
import { assert } from "node-opcua-assert";
2✔
7
import { DataType } from "node-opcua-basic-types";
2✔
8
import { AttributeIds, NodeClass } from "node-opcua-data-model";
2✔
9
import { make_warningLog } from "node-opcua-debug";
2✔
10
import type { ExtensionObject } from "node-opcua-extension-object";
2✔
11
import { type INodeId, NodeId, NodeIdType } from "node-opcua-nodeid";
2✔
12
import { DataChangeFilter, EventFilter } from "node-opcua-service-filter";
2✔
13
import { DeadbandType } from "node-opcua-service-subscription";
2✔
14
import { type StatusCode, StatusCodes } from "node-opcua-status-code";
2✔
15
import type { ReadValueIdOptions } from "node-opcua-types";
2✔
16

2✔
17
const warningLog = make_warningLog(__filename);
2✔
18

2✔
19
function isNumberDataType(node: UAVariable): boolean {
27✔
20
    const n = node.dataType as INodeId;
27✔
21
    if (n.namespace === 0 && n.identifierType === NodeIdType.NUMERIC && n.value < 22) {
27✔
22
        switch (n.value) {
27✔
23
            case DataType.Float:
27✔
24
            case DataType.Double:
27✔
25
            case DataType.Byte:
27✔
26
            case DataType.SByte:
27✔
27
            case DataType.Int16:
27✔
28
            case DataType.Int32:
27✔
29
            case DataType.Int64:
27✔
30
            case DataType.UInt16:
27✔
31
            case DataType.UInt32:
27✔
32
            case DataType.UInt64:
27✔
33
                return true;
20✔
34
            default:
27✔
35
                return false;
7✔
36
        }
27✔
37
    }
27✔
38
    const dataType = node.addressSpace.findDataType(node.dataType)!;
19!
39
    const dataTypeNumber = node.addressSpace.findDataType("Number")!;
×
40
    return dataType.isSubtypeOf(dataTypeNumber);
×
41
}
19✔
42

2✔
43
function __validateDataChangeFilter(filter: DataChangeFilter, itemToMonitor: ReadValueIdOptions, node: UAVariable): StatusCode {
53✔
44
    assert(itemToMonitor.attributeId === AttributeIds.Value);
53✔
45
    if (node.nodeClass !== NodeClass.Variable) {
53!
46
        return StatusCodes.BadNodeIdInvalid;
×
47
    }
×
48

53✔
49
    if (filter.deadbandType !== DeadbandType.None) {
53✔
50
        // if node is not Numerical=> DataChangeFilter
27✔
51
        assert(node.dataType instanceof NodeId);
27✔
52
        if (!isNumberDataType(node)) {
27✔
53
            return StatusCodes.BadFilterNotAllowed;
7✔
54
        }
7✔
55
    }
27✔
56

49✔
57
    if (filter.deadbandType === DeadbandType.Percent) {
53✔
58
        if (filter.deadbandValue < 0 || filter.deadbandValue > 100) {
7✔
59
            return StatusCodes.BadDeadbandFilterInvalid;
2✔
60
        }
2✔
61

7✔
62
        // node must also have a valid euRange
7✔
63
        if (!node.getChildByName("EURange", 0)) {
7✔
64
            warningLog(" node has no euRange ! Dead band Percent cannot be used on node " + node.nodeId.toString());
1✔
65
            return StatusCodes.BadMonitoredItemFilterUnsupported;
1✔
66
        }
1✔
67
    }
7✔
68
    return StatusCodes.Good;
49✔
69
}
49✔
70

2✔
71
export function validateFilter(filter: ExtensionObject | null, itemToMonitor: ReadValueIdOptions, node: BaseNode): StatusCode {
14,692✔
72
    // handle filter information
14,800✔
73
    if (filter && filter instanceof EventFilter && itemToMonitor.attributeId !== AttributeIds.EventNotifier) {
14,800✔
74
        // invalid filter on Event
1✔
75
        return StatusCodes.BadFilterNotAllowed;
1✔
76
    }
1✔
77

14,799✔
78
    if (filter && filter instanceof DataChangeFilter && itemToMonitor.attributeId !== AttributeIds.Value) {
14,800✔
79
        // invalid DataChange filter on non Value Attribute
7✔
80
        return StatusCodes.BadFilterNotAllowed;
7✔
81
    }
7✔
82

14,799✔
83
    if (filter && itemToMonitor.attributeId !== AttributeIds.EventNotifier && itemToMonitor.attributeId !== AttributeIds.Value) {
14,800!
84
        return StatusCodes.BadFilterNotAllowed;
×
85
    }
×
86

14,799✔
87
    if (filter instanceof DataChangeFilter) {
14,800✔
88
        return __validateDataChangeFilter(filter, itemToMonitor, node as UAVariable);
53✔
89
    }
53✔
90

14,784✔
91
    return StatusCodes.Good;
14,784✔
92
}
14,784✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc