### Subscribe to Node Value Changes in TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates how to create a node subscription using codabix.subscribeNodes and handle updates via addValueChangedEventListener. It includes setup, event handling, and proper cleanup of resources after a specified duration. ```typescript runtime.handleAsync(async function () { let nodeA = codabix.findNode("/Nodes/A", true); let nodeB = codabix.findNode("/Nodes/B", true); // Subscribe nodes with 200ms polling interval let subscription = codabix.subscribeNodes([nodeA, nodeB], 200, false); logger.log(`Subscription created. Interval=${subscription.interval}`); // Handle value changes with event listener let valueChangeListener: codabix.NodeValueChangedEventListener = e => { if (e.isValueChanged) { logger.log(`Value changed: Old=${e.oldValue?.value}, New=${e.newValue?.value}`); } }; // Add listener without creating implicit subscription (we already have one) nodeA.addValueChangedEventListener(valueChangeListener, false); nodeB.addValueChangedEventListener(valueChangeListener, false); // Run for 60 seconds then cleanup await timer.delayAsync(60 * 1000); codabix.unsubscribeNodes(subscription); nodeA.removeValueChangedEventListener(valueChangeListener); nodeB.removeValueChangedEventListener(valueChangeListener); logger.log("Subscription stopped."); }()); ``` -------------------------------- ### Find Nodes in Codabix using TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates how to locate nodes within the Codabix node tree using various identifiers like path strings, local IDs, GUIDs, or NodeIdentifier objects. It handles cases where nodes might not exist and shows how to access node properties. ```typescript runtime.handleAsync(async function () { // Find a node by path (throws if not found when second parameter is true) let temperatureNode = codabix.findNode("/Nodes/Temperature", true); // Find a node without throwing (returns null if not found) let optionalNode = codabix.findNode("/Nodes/MayNotExist"); if (optionalNode) { logger.log("Node found: " + optionalNode.name); } // Find child nodes relative to a parent let parentNode = codabix.findNode("/Nodes/MyParent", true); let childNode = parentNode.findNode("ChildName", true); // Access node properties logger.log(`Node: ${temperatureNode.name}, Value: ${temperatureNode.value?.value}`); }()); ``` -------------------------------- ### Send REST API Requests using net.httpClient Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates how to perform GET and POST requests to external REST APIs. It handles JSON parsing, request headers, and error management within an asynchronous runtime context. ```typescript runtime.handleAsync(async function () { let temperatureNode = codabix.findNode("/Nodes/Temperature", true); while (true) { let valueToWrite: codabix.NodeValue; try { let response = await net.httpClient.sendAsync({ url: "https://api.openmeteo.com/observations/openmeteo/1001/t2" }); let result = JSON.parse(response.content!.body); valueToWrite = new codabix.NodeValue(result[1]); } catch (e) { logger.logWarning("Could not retrieve weather data: " + e); valueToWrite = new codabix.NodeValue(null, undefined, { statusCode: codabix.NodeValueStatusCodeEnum.Bad, statusText: String(e) }); } await codabix.writeNodeValueAsync(temperatureNode, valueToWrite); await timer.delayAsync(5000); } }()); ``` ```typescript runtime.handleAsync(async function () { let response = await net.httpClient.sendAsync({ url: "http://localhost:8181/api/json", method: "POST", content: { headers: { "content-type": "application/json" }, body: JSON.stringify({ username: "demo@user.org", password: codabix.security.decryptPassword(""), browse: { na: "/Nodes" } }) } }); if (response.content) { let jsonResult = JSON.parse(response.content.body); logger.log("API Response: " + JSON.stringify(jsonResult)); } }()); ``` -------------------------------- ### Register Method Commands with Arguments in TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Explains how to handle input and output arguments within a method command using NodeCommandContext. This allows for dynamic logic based on provided inputs and returning results to the caller. ```typescript runtime.handleAsync(async function () { let methodNode = codabix.findNode("/Nodes/PlayRockPaperScissors", true); // Requires: Input argument 'PlayerHand' (Int32), Output argument 'Result' (String) methodNode.registerCommand({ executeAsync(context: codabix.NodeCommandContext): Promise { let moves = ["Rock", "Paper", "Scissors"]; // Read input argument (1=Rock, 2=Paper, 3=Scissors) let playerHand = context.inputArguments[0].value as number; let codabixHand = Math.floor(Math.random() * 3) + 1; // Determine winner let winner = "Player"; if (playerHand == codabixHand) { winner = "neither"; } else if ((playerHand === 1 && codabixHand === 2) || (playerHand === 2 && codabixHand === 3) || (playerHand === 3 && codabixHand === 1)) { winner = "Codabix"; } // Set output argument context.outputArguments[0].value = `Player: '${moves[playerHand - 1]}', Codabix: '${moves[codabixHand - 1]}' -> Winner: ${winner}`; return Promise.resolve(); } }); }()); ``` -------------------------------- ### Perform File I/O Operations Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates asynchronous file reading and writing using the io.file namespace, including streaming via readers and writers for large data handling. ```typescript runtime.handleAsync(async function () { const filePath = "C:/CodabixData/output.txt"; await io.file.writeAllTextAsync(filePath, "Hello, Codabix!\nLine 2"); let content = await io.file.readAllTextAsync(filePath); logger.log("File content: " + content); if (await io.file.existsAsync(filePath)) { logger.log("File exists"); } let reader = await io.file.openReaderAsync(filePath); try { let line: string | null; while ((line = await reader.readLineAsync()) !== null) { logger.log("Line: " + line); } } finally { await reader.closeAsync(); } let writer = await io.file.openWriterAsync("C:/CodabixData/log.txt", true); try { await writer.writeLineAsync("Log entry: " + new Date().toISOString()); } finally { await writer.closeAsync(); } }()); ``` -------------------------------- ### Create Nodes in Codabix using TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Illustrates the creation of new nodes within the Codabix node tree. This includes creating folder nodes and value nodes with specified types and enabling history logging for data changes. ```typescript runtime.handleAsync(async function () { let parentNode = codabix.findNode("/Nodes", true); // Create a folder node let folderNode = codabix.createNode({ name: "Demo Nodes", parentIdentifier: parentNode.identifier, class: codabix.NodeClassEnum.Folder }); // Create value nodes with different types let intNode = codabix.createNode({ name: "Counter", parentIdentifier: folderNode.identifier, class: codabix.NodeClassEnum.Value, valueType: codabix.Types.int32 }); // Create a node with history enabled let temperatureNode = codabix.createNode({ name: "Temperature", displayName: "Temperature (°C)", parentIdentifier: folderNode.identifier, class: codabix.NodeClassEnum.Value, valueType: codabix.Types.double, historyOptions: codabix.NodeHistoryOptions.Subscription | codabix.NodeHistoryOptions.ValueChange }); logger.log("Created nodes successfully"); }()); ``` -------------------------------- ### Register Simple Method Commands in TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Shows how to register a basic method command on a node using registerCommand. The executeAsync handler defines the logic to be performed when the method is invoked. ```typescript runtime.handleAsync(async function () { let methodNode = codabix.findNode("/Nodes/HelloWorld", true); methodNode.registerCommand({ executeAsync(): Promise { logger.log("Hello World!"); return Promise.resolve(); } }); }()); ``` -------------------------------- ### Execute Method Nodes Programmatically in TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates how to trigger a method node execution using codabix.executeNodeCommandsAsync. It covers writing input values to nodes and retrieving output results after execution. ```typescript runtime.handleAsync(async function () { let methodNode = codabix.findNode("/Nodes/MyMethod", true); let inputArgument = methodNode.findNode("IN/MyInput1", true); let outputArgument = methodNode.findNode("OUT/MyOutput1", true); // Set input argument before calling await codabix.writeNodeValueAsync(inputArgument, "some value"); try { await codabix.executeNodeCommandsAsync(methodNode); // Retrieve output argument value let outputValue = outputArgument.value?.value; logger.log("Method output: " + outputValue); } catch (e) { logger.logError("Could not call method node: " + e); } }()); ``` -------------------------------- ### Register Custom Node Reader with Dynamic Filename Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates how to register a custom asynchronous node reader that dynamically generates a filename based on the current date. This allows for real-time updates to node values. ```typescript runtime.handleAsync(async function () { let fileNameNode = codabix.findNode("/Nodes/CSV-Test/Filename", true); fileNameNode.registerReader({ readValuesAsync() { // Generate dynamic filename with current date let fileTimeStamp = runtime.date.format(Date.now(), "yyyy-MM-dd", true, false); let value = new codabix.NodeValue(fileTimeStamp); void codabix.writeNodeValueAsync(fileNameNode, value); return Promise.resolve(); } }); }()); ``` -------------------------------- ### SignalR Web Client for Node Value Changes Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Illustrates how to use the SignalR client library to connect to Codabix and subscribe to real-time changes in node values. It logs the new value to the console and updates an HTML element. ```javascript import * as signalR from './lib/signalR/index.js'; // Create client and connect let client = new signalR.Client('http://localhost:8181'); await client.connect('admin', '1234'); // Subscribe to node value changes const nodePaths = ['/Nodes/Demo/integerNode', '/Nodes/Demo/stringNode']; for (const nodePath of nodePaths) { const channel = client.subscribeValueChanges([nodePath]); channel.subscribe({ next: (e) => { console.log(`Node ${nodePath} changed to: ${e.newValue.value}`); document.getElementById('node-value').innerHTML = e.newValue.value; }, complete: () => { console.log('Subscription completed.'); }, error: (err) => { console.error('Subscription error:', err); } }); } ``` -------------------------------- ### Logging API Usage Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Shows how to use the `logger` namespace to write messages to the script log at different severity levels (Debug, Info, Warning, Error). It also demonstrates logging with a custom level. ```typescript runtime.handleAsync(async function () { logger.logDebug("Debug message for troubleshooting"); logger.logInfo("Informational message"); logger.logWarning("Warning: potential issue detected"); logger.logError("Error: operation failed"); // Generic log with custom level logger.log("Custom level message", logger.LogLevel.Info); }()); ``` -------------------------------- ### Manage Timers and Scheduling Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Covers the use of the timer namespace for delays, one-time timeouts, repeating intervals, and complex daily task scheduling. ```typescript runtime.handleAsync(async function () { logger.log("Starting..."); await timer.delayAsync(2000); logger.log("2 seconds passed"); let timeoutHandle = timer.setTimeout(() => { logger.log("Timeout fired after 5 seconds"); }, 5000); let intervalHandle = timer.setInterval(() => { logger.log("Interval tick every 1 second"); }, 1000); await timer.delayAsync(10000); timer.clearInterval(intervalHandle); logger.log("Interval stopped"); }()); ``` ```typescript runtime.handleAsync(async function () { async function waitUntilAsync(date: Date) { while (true) { let timeToWait = date.getTime() - Date.now(); if (timeToWait > 0) { await timer.delayAsync(Math.min(5000, timeToWait)); } else { return; } } } let currentDate = new Date(); let targetDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate()); targetDate.setHours(14); targetDate.setMinutes(0); if (targetDate.getTime() - currentDate.getTime() < 0) { targetDate.setDate(targetDate.getDate() + 1); } while (true) { logger.log("Wait until: " + targetDate); await waitUntilAsync(targetDate); try { logger.logWarning("Executing scheduled task at 14:00!"); } catch (e) { logger.logError("Error in scheduled function: " + e); } targetDate.setDate(targetDate.getDate() + 1); } }()); ``` -------------------------------- ### Read and Write Node Values in Codabix using TypeScript Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Demonstrates asynchronous reading and writing of node values using Codabix API. Supports reading multiple values, writing simple values, values with custom timestamps and statuses, and writing multiple values simultaneously, including bad status codes. ```typescript runtime.handleAsync(async function () { let nodeA = codabix.findNode("/Nodes/A", true); let nodeB = codabix.findNode("/Nodes/B", true); // Read multiple node values let values = await codabix.readNodeValuesAsync([nodeA, nodeB]); for (let i = 0; i < values.length; i++) { let value = values[i]; if (value && !value.status.isBad) { logger.log(`Node value: ${value.value}, Timestamp: ${value.timestamp}`); } } // Write a simple value await codabix.writeNodeValueAsync(nodeA, 42); // Write a value with custom timestamp and status let nodeValue = new codabix.NodeValue( 100.5, // value new Date(), // timestamp codabix.NodeValueStatusCodeEnum.Good // status ); await codabix.writeNodeValueAsync(nodeB, nodeValue); // Write multiple values at once await codabix.writeNodeValuesAsync([ { node: nodeA, value: 10 }, { node: nodeB, value: 20 } ]); // Write a bad status value (e.g., when data source fails) let badValue = new codabix.NodeValue(null, undefined, { statusCode: codabix.NodeValueStatusCodeEnum.Bad, statusText: "Connection lost" }); await codabix.writeNodeValueAsync(nodeA, badValue); }()); ``` -------------------------------- ### Retry Logic for Writing Node Values Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Offers a robust asynchronous function `writeNodeValuesWithRetryAsync` that repeatedly attempts to write node values until successful. It logs warnings for failed writes and retries after a delay. ```typescript async function writeNodeValuesWithRetryAsync(nodeValues: { node: codabix.Node, value: codabix.NodeValue | codabix.NodeValueType }[]) { while (true) { let results = await codabix.writeNodeValuesAsync(nodeValues); let success = true; for (let i = 0; i < results.length; i++) { let result = results[i]; if (!result || result.isBad) { logger.logWarning(`Could not write '${nodeValues[i].node}': ${result?.statusText || "Error"}`); success = false; break; } } if (!success) { await timer.delayAsync(1000); continue; } return; } } // Usage runtime.handleAsync(async function () { let node1 = codabix.findNode("/Nodes/A", true); let node2 = codabix.findNode("/Nodes/B", true); await writeNodeValuesWithRetryAsync([ { node: node1, value: 100 }, { node: node2, value: 200 } ]); }()); ``` -------------------------------- ### Retry Logic for Reading Node Values Source: https://context7.com/traeger-gmbh/codabix-samples/llms.txt Provides a robust asynchronous function `readNodeValuesWithRetryAsync` that repeatedly attempts to read node values until successful. It logs warnings for failed reads and retries after a delay. ```typescript async function readNodeValuesWithRetryAsync(nodes: codabix.Node[]) { while (true) { let results = await codabix.readNodeValuesAsync(nodes); let success = true; for (let i = 0; i < results.length; i++) { let result = results[i]; if (!result || result.status.isBad) { logger.logWarning(`Could not read '${nodes[i]}': ${result?.status.statusText || "Error"}`); success = false; break; } } if (!success) { await timer.delayAsync(1000); continue; } return results as codabix.NodeValue[]; } } // Usage runtime.handleAsync(async function () { let node1 = codabix.findNode("/Nodes/A", true); let node2 = codabix.findNode("/Nodes/B", true); let values = await readNodeValuesWithRetryAsync([node1, node2]); logger.log("Values: " + values.map(v => v.value).join(", ")); }()); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.