Call for Sales and Service: 1-800-889-3751

Programming in .NET

Create a new .NET6 Console Application:

Install the project to your preferred location. Use a name that describes your project. 

NuGet Packages for .Net Programming.

The following packages are available on NuGet:

ParallaxControlSystemLibrary and ParallaxUnityLibrary.

If your IDE supports nuget, search the packages and add them to your project.

Note: The program that is loaded to the raspberry pi uses the 'ParallaxControlSystemLibrary' package. The program that is used to build your touch panel is imported in the Unity Editor IDE 'ParallaxUnityLibrary'. These are two separate solutions. 

Direct links:

For Logic Program:

https://www.nuget.org/packages/ParallaxControlSystemLibrary/

For Unity User-Interface Program:

https://www.nuget.org/packages/ParallaxUnityLibrary/

Publishing and uploading the application to the Control Processor:

 

Publish the application:

 

Use the following setup configuration:

 

After you publish, it will build an executable binary file. Upload this to the control processor by its web page:

 

Locate the binary executable (it will not have a file extension):

 

Select file -> Upload, Load, Allow, Stop, Start.

If you check the console log, the program should now be running.

 

Running the program on a local machine for testing:

Publish the program to your machine and run the console app locally for testing.

Note: if your code tries to access onboard serial I/O without first checking if the device supports it, the console app may throw an error. 

 

Class: Program

The Program class is a default class created by .NET6, it is the entry point of your program.

Methods

public static void Main()

The Main() method is the entry point of the console application. 

Example Usage

public static void Main() {

try {

Console.WriteLine("Console Program Starting...");

//listen for a touch panel to come online

ParallaxControlSystemLibrary.TouchpanelCommunication.StartTouchPanelServer(50001);

}

catch (Exception e) { Console.WriteLine("\nException in startup sequence {0}.", e.Message);}

}

Remarks

The Program class is designed to be run on a control processor as part of a larger control system. It is an example of how to start up the touchpanel server using the Parallax Control System Library.

To use the Program class, you will need to have a working installation of the Parallax Control System Library package, and the .NET 6.0 runtime on the control processor. You will also need to modify the port number to match the port number you want to use for the touch panel server.

 

Function: AnalogInput

The AnalogInput function is a method of the Parallax Control System Library. It is used to set the level of an analog object, such as a gauge, meter, or slider.

Parameters

  • analogJoinInstanceId: The unique ID used to identify the analog object.
  • level: The level to set the gauge, meter, or slider.

Example Usage

AnalogInput(1, 0.75f);

Remarks

The AnalogInput function is used to update the value of an analog object and send the updated value to any connected touchpanels. It first checks if an analog object with the given ID already exists in the _analogMembersList. If it does, the function updates the value of the existing object. If it does not, the function adds a new analog object to the list.

The function then constructs a command string to send to the touchpanels, using the analogJoinInstanceId and level parameters. It sends the command to all connected touchpanels within the same program slot, using the SendToPanel method.

Note that the AnalogInput function is part of a larger control system and is meant to be used in conjunction with other methods and classes in the Parallax Control System Library. To use the function, you will need to have a working installation of the library and an understanding of how the control system works.


 

Function: StringInput

The StringInput function is a method of the Parallax Control System Library. It is used to send dynamic text data to a touchpanel.

Parameters

  • serialJoinInstanceId: The unique ID used to identify the dynamic text object.
  • text: The text data to send to the touchpanel.

Example Usage

StringInput(1, "Hello, world!");

Remarks

The StringInput function is used to update the value of a dynamic text object and send the updated value to any connected touchpanels. It first checks if a dynamic text object with the given ID already exists in the _serialMembersList. If it does, the function updates the value of the existing object. If it does not, the function adds a new dynamic text object to the list.

The function then constructs a command string to send to the touchpanels, using the serialJoinInstanceId and text parameters. It sends the command to all connected touchpanels within the same program slot, using the SendToPanel method.

Note that the StringInput function is part of a larger control system and is meant to be used in conjunction with other methods and classes in the Parallax Control System Library. To use the function, you will need to have a working installation of the library and an understanding of how the control system works.

Function: DigitalInput

The DigitalInput function is a method of the Parallax Control System Library. It is used to toggle a digital join in response to a button press.

Parameters

  • buttonJoinToToggle: The unique ID used to identify the digital join.
  • buttonFBState: The state of the button.

Example Usage

DigitalInput(1, 1);

Remarks

The DigitalInput function is used to update the value of a digital join and send the updated value to any connected touchpanels. It first checks if a digital join with the given ID already exists in the _digitalMembersList. If it does, the function updates the value of the existing join. If it does not, the function adds a new digital join to the list.

The function then constructs a command string to send to the touchpanels, using the buttonJoinToToggle and buttonFBState parameters. It sends the command to all connected touchpanels within the same program slot, using the SendToPanel method.

Note that the DigitalInput function is part of a larger control system and is meant to be used in conjunction with other methods and classes in the Parallax Control System Library. To use the function, you will need to have a working installation of the library and an understanding of how the control system works.

Function: DynamicObject

The DynamicObject function is a method of the Parallax Control System Library. It is used to update a dynamic object on the touchpanel interface.

Parameters

  • instanceId: The unique ID used to identify the dynamic object.
  • values: An array of string values to update the dynamic object with.

Example Usage

DynamicObject(1, new string[]{"value1", "value2", "value3"});

Remarks

The DynamicObject function is used to update a dynamic object on the touchpanel interface and send the updated value to any connected touchpanels. It first checks if a dynamic object with the given ID already exists in the _dynamicObjectMembersList. If it does, the function updates the value of the existing object. If it does not, the function adds a new dynamic object to the list.

The function then constructs a command string to send to the touchpanels, using the instanceId parameter to identify the object and the values parameter to update the object. It converts the values array to a JSON string before including it in the command string. The function sends the command to all connected touchpanels within the same program slot, using the SendToPanel method.

Note that the DynamicObject function is part of a larger control system and is meant to be used in conjunction with other methods and classes in the Parallax Control System Library. To use the function, you will need to have a working installation of the library and an understanding of how the control system works.

 

Setting the Length of the DynamicObject Array:

Currently, it is required to set the length of the DynamicObject array using the SetAnalogValue function. Simply utilize the same InstanceId to set the length.

UserInterface.SetAnalogValue(101,circuitLabelsArray.Length);
UserInterface.SetDynamicObject(101, circuitLabelsArray);

 

The StartTouchPanelServer function is a static method in the TouchpanelCommunication class of the ParallaxControlSystemLibrary namespace. It starts the Parallax Control System Tcp Listener on the specified port. This function is called in the ControlSystem class to start the server.

The function takes one parameter, which is the port number to listen on. This should be a number between 50001 and 50010 for Program Slots 1 - 10. Only one program or port per console app is allowed. If you require more slots, create a new solution with the associated slot port. The server program port is reserved for the Unity touchpanel. If you require a TcpServer, create your own outside of this range.

The function starts a global timer using a Task.Run() method call to the GTimer() method in the GlobalTimer class. It also starts the SetupTpServer() method using another Task.Run() method call.

The function does not return anything, it just starts the Tcp Listener on the specified port. Any errors or exceptions that occur during the execution of this function will be displayed in the console.

Events:

ParallaxControlSystemLibrary is a C# library that provides event handlers for panel inputs, including digital, analog, and string inputs. These event handlers can be used to respond to user input on the control panel and perform actions based on that input.

The library includes the following events:

  1. RxPanelDigital: This event is raised when a digital input is received from the control panel. The event handler takes an integer parameter representing the ID of the digital input that was received.
  2. RxPanelAnalog: This event is raised when an analog input is received from the control panel. The event handler takes two parameters: an integer representing the ID of the analog input, and a float representing the value of the analog input.
  3. RxPanelString: This event is raised when a string input is received from the control panel. The event handler takes two parameters: an integer representing the ID of the string input, and a string representing the value of the string input.

To use these events, you need to register event handlers for each of them in your application. For example:

using ParallaxControlSystemLibrary;
public class MyControlSystem {
public MyControlSystem() {
// Register event handlers
ParallaxControlSystemLibrary.OnRxPanelDigital += HandleDigitalInput;
ParallaxControlSystemLibrary.OnRxPanelAnalog += HandleAnalogInput;
ParallaxControlSystemLibrary.OnRxPanelSerial += HandleStringInput;
}
 
private void HandleDigitalInput(int id) {
// Handle digital input
}
 
private void HandleAnalogInput(int id, float value) {
// Handle analog input
}
private void HandleStringInput(int id, string value) {
// Handle string input
}
}

In this example, the MyControlSystem class registers event handlers for each of the events. When an input is received from the control panel, the corresponding event handler is called with the ID and value of the input. You can then perform the appropriate action based on the input.

The DigitalInputOutput class is a class library that provides functionality for interacting with digital input and output pins on a GPIO controller. It contains several methods for opening GPIO pins as input or output, setting GPIO pins to high or low, and closing GPIO pins. It also contains an event that can be used to respond to pin value changes.

Class Members:

  • GpioController _controller: A private instance of a GpioController that is used to interact with the GPIO pins.
  • public delegate void GpioResponseEvent(int pinNumber, PinValue pinValue, PinEventTypes pinEventTypes): A delegate event that is triggered when a pin value changes.
  • public static event GpioResponseEvent OnGpioResponseEvent;: A static event that can be subscribed to in order to handle pin value changes.
  • public void OpenGpioAsInputPullUp(int gpioNumber): A method that opens a GPIO pin as an input with pull-up resistors.
  • public void OpenGpioAsInputPullDown(int gpioNumber): A method that opens a GPIO pin as an input with pull-down resistors.
  • public void OpenGpioAsInput(int gpioNumber): A method that opens a GPIO pin as an input.
  • public void OpenGpioAsOutput(int gpioNumber): A method that opens a GPIO pin as an output.
  • public void CloseGpio(int gpioNumber): A method that closes a GPIO pin.
  • public void SetGpioHigh(int gpioNumber): A method that sets the value of a GPIO pin to high.
  • public void SetGpioLow(int gpioNumber): A method that sets the value of a GPIO pin to low.
  • private void Callback(object sender, PinValueChangedEventArgs pinvaluechangedeventargs): A private method that is called when the value of a GPIO pin changes. This method triggers the OnGpioResponseEvent event.
  •  

Example Usage:

//Create a new instance of the DigitalInputOutput class
DigitalInputOutput digitalIO = new DigitalInputOutput();
//Open GPIO pin 4 as an input with pull-up resistors
digitalIO.OpenGpioAsInputPullUp(4);
//Subscribe to the OnGpioResponseEvent event to handle pin value changes
DigitalInputOutput.OnGpioResponseEvent += HandlePinValueChange;
//Handle pin value changes
private void HandlePinValueChange(int pinNumber, PinValue pinValue, PinEventTypes pinEventTypes) {
Console.WriteLine($"Pin {pinNumber} changed to {pinValue}");
}
//Close GPIO pin 4
digitalIO.CloseGpio(4);

The ParallaxControlSystemLibrary.ComPorts class is a utility class that provides a simple interface for working with serial ports on a Raspberry Pi device. It provides methods for opening, closing, and sending data over serial ports.

 

Class Members:

 

The following are the members of the ParallaxControlSystemLibrary.ComPorts class:

 

  1. SerialResponseEvent:

This is a delegate type that defines the signature for the event handlers that will be used to handle the data received events for each serial port. There are four event handlers defined for four different serial ports: OnSerialCom1ResponseEvent, OnSerialCom2ResponseEvent, OnSerialCom3ResponseEvent, and OnSerialCom4ResponseEvent. These event handlers take a string parameter that represents the data received over the serial port.

 

  1. rs232:

This is a static list of SerialPort objects that represents the open serial ports. This list is used to handle data received events and to close the serial ports when necessary.

 

  1. OpenComPort:

This method opens a specified serial port. It takes four parameters: the port number, the baud rate, the parity, and the stop bits. The parity and stop bits parameters are optional and have default values of Parity.None and StopBits.One, respectively. The method creates a new SerialPort object with the specified port name and settings, opens the serial port, and registers an event handler to handle data received events.

 

  1. CloseComPort:

This method closes a specified serial port. It takes one parameter: the port number. The method waits for any pending data to be transmitted before closing the serial port and removing it from the rs232 list.

 

  1. SendByteArray:

This method sends a byte array over a specified serial port. It takes two parameters: the port number and the byte array. The method checks to make sure the serial port is open before sending the byte array.

 

Example Usage:

Here is an example usage of the ParallaxControlSystemLibrary.ComPorts class:

 
using System;
using ParallaxControlSystemLibrary;
class Program {
static void Main(string[] args) {
// Open serial port 1 with a baud rate of 9600
ComPorts.OpenComPort(1, 9600);
// Send "Hello, World!" over serial port 1
ComPorts.SendByteArray(1, "Hello, World!");
// Wait for a response
ComPorts.OnSerialCom1ResponseEvent += (val) => { Console.WriteLine("Received: {0}", val); };
Console.ReadLine();
// Close serial port 1
ComPorts.CloseComPort(1);
}
}

In this example, we first open serial port 1 with a baud rate of 9600. We then send the string "Hello, World!" over the serial port. We register an event handler to handle data received events for serial port 1, and then wait for a response. When a response is received, we print it to the console. Finally, we close serial port 1.

The ControlEngineInterfaceProtocol class is a TCP/IP server implementation that listens for incoming connections on a specific port and waits for messages to call methods on other classes. This class is part of the Parallax Control System Library and is responsible for handling the communication between the control engine and other parts of the system.

 

Constructor

The constructor for ControlEngineInterfaceProtocol takes a single parameter, which is the port number that the server should listen on. It starts a new thread to wait for incoming connections on this port.

 

Example Usage

ControlEngineInterfaceProtocol protocol = new ControlEngineInterfaceProtocol(8888);
 

Events

The ControlEngineInterfaceProtocol class provides an event, OnControlEngineInterfaceEvent, which is raised when a message is received that is intended to call a method on another class. This event is used to notify the system that a method should be called on a specific class.

 

Example Usage

ControlEngineInterfaceProtocol.OnControlEngineInterfaceEvent += MyClass.HandleControlEngineInterfaceEvent;
 

Methods

The ControlEngineInterfaceProtocol class provides no public methods. All methods are private and are used internally to implement the server functionality.

 

Example Usage

The following code shows an example of how to use the ControlEngineInterfaceProtocol class:

 
// Start the server on port 8888
 ControlEngineInterfaceProtocol protocol = newControlEngineInterfaceProtocol(8888);
// Register an event handler to be notified when a message is received
ControlEngineInterfaceProtocol.OnControlEngineInterfaceEvent += MyClass.HandleControlEngineInterfaceEvent;
// Example method to handle the OnControlEngineInterfaceEvent
event public static void HandleControlEngineInterfaceEvent(string classToCall, string methodToCall) {
// Look up the class to call and the method to call, and invoke the method Type
classType = Type.GetType(classToCall);
MethodInfo methodInfo = classType.GetMethod(methodToCall);
methodInfo.Invoke(null, null); }

To view the console log:

SSH to the device:

ssh pi@

password:

Connect through ssh terminal:

Parallax Console Commands:

log: displays console prints from the dotnet program, I.E., Console.WriteLine("hello word"); will print hello world in the console. Press Ctrl + x to exit the console log.

Other helpful linux commands:

pinout:

htop: displays cpu, ram and storage levels

 

CONSOLE COMMANDS:

“start” to start the program (required after uploading a new program).

“stop” to stop the program (required before uploading a new program via FTP).

“allow” allow the newly uploaded file to run (required after uploading a new program).

“log” shows the programs debug output in real-time.

“pinout” shows the gpio pins.

“show_gpio” shows the gpio pins in use or available for programming.

 

Other useful commands:

“htop” to shows running processes and hardware performance.

“sudo reboot” restarts processor hardware.

## Manual: Parallax Control System Library - MQTT Broker Program

 

 

### Class Overview: `MqttBrokerProgram`

 

The `MqttBrokerProgram` class provides static methods for starting an MQTT broker, creating a managed MQTT client, and performing operations like publishing, subscribing, and unsubscribing on the client side.

 

### Client Side Delegates and Events:

 

- `MqttClientIsConnectedAsync`: Delegate for MQTT client connection event.

- `OnMqttClientConnectedAsync`: Event invoked when the MQTT client is connected.

 

- `MqttClientIsApplicationMessageReceivedAsync`: Delegate for MQTT client message received event.

- `OnMqttClientApplicationMessageReceivedAsync`: Event invoked when the MQTT client receives a message.

 

### Public Methods:

 

Note: the MqttBroker in .net is being deprecated, we will be using Node-Red as the primary Mqtt Broker. Only use MqttClient in .net to connect to the node-red broker. However, currently the mqttbroker may still work on the .net side. Also note that currently, the Mqtt Version is 3.1.1 and will not yet work with the latest V5.

 

#### 1. `StartMqttBroker(string username, string password, int brokerPort = 1883)`

 

Starts the MQTT broker with the given username, password, and port.

 

Parameters:

- `username`: The username for the broker.

- `password`: The password for the broker.

- `brokerPort`: The port on which the broker runs (default is 1883).

 

Usage:

```csharp

MqttBrokerProgram.StartMqttBroker("yourUsername", "yourPassword", 1883);

```

 

#### 2. `DisconnectManagedMqttClientAsync()`

 

Disconnects the managed MQTT client gracefully.

 

Usage:

```csharp

await MqttBrokerProgram.DisconnectManagedMqttClientAsync();

```

 

Note: use this function in your console program to create your mqtt client and to connect to the node-red mqtt broker. Both the console program and touchpanel program will connect to the node-red broker which will act as the central point of communication.

 

#### 3. `CreateManagedMqttClientAsync(string username, string password, string brokerIp, int brokerPort, string clientId)`

 

Creates a managed MQTT client with the specified parameters.

 

Parameters:

- `username`: The username for the client.

- `password`: The password for the client.

- `brokerIp`: IP address of the MQTT broker.

- `brokerPort`: The port on which the broker runs.

- `clientId`: A unique identifier for the client.

 

Usage:

```csharp

await MqttBrokerProgram.CreateManagedMqttClientAsync("yourUsername", "yourPassword", "127.0.0.1", 1883, "uniqueClientId");

```

 

#### 4. `SubscribeClientAsync(string topic)`

 

Allows the client to subscribe to a specific topic.

 

Parameters:

- `topic`: The MQTT topic to subscribe to.

 

Usage:

```csharp

await MqttBrokerProgram.SubscribeClientAsync("yourTopic");

```

 

#### 5. `UnsubscribeClientAsync(string topic)`

 

Allows the client to unsubscribe from a specific topic.

 

Parameters:

- `topic`: The MQTT topic to unsubscribe from.

 

Usage:

```csharp

await MqttBrokerProgram.UnsubscribeClientAsync("yourTopic");

```

 

#### 6. `PublishClientAsync(string topic, string payload)`

 

Publishes a message to a specific topic with the provided payload.

 

Parameters:

- `topic`: The MQTT topic to which the message is to be published.

- `payload`: The message content.

 

Usage:

```csharp

await MqttBrokerProgram.PublishClientAsync("yourTopic", "yourPayload");

```

 

### Notes:

- It's recommended to handle events such as `OnMqttClientConnectedAsync` and `OnMqttClientApplicationMessageReceivedAsync` for notifications and business logic needs.

- Always ensure that the credentials (username & password) are kept secure and are not exposed to unauthorized users.

- The library provides the option to add encryption (for example, using a certificate); however, this feature is commented out in the provided code.

 

### Conclusion:

The `MqttBrokerProgram` class offers a collection of tools and functionalities to interact with MQTT services, especially focused on broker and client operations. Always ensure a proper management of credentials and adopt best practices for establishing secure connections and interactions.

# User Guide: Parallax Control System Library - MqttTouchpanelMessenger

 

**Namespace**: ParallaxControlSystemLibrary

 

**Dependencies**:

```csharp

using Newtonsoft.Json;

```

 

## Overview:

`MqttTouchpanelMessenger` is a class dedicated to sending different types of data through MQTT. This guide will explain the different methods available and how to use them effectively to send your data.

 

### Method Descriptions:

 

  1. ### `SendDigitalData(int instanceId, bool value, string topic)`

  

   Send a digital data type to a specified topic.

  

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `value`: Boolean value to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   MqttTouchpanelMessenger.SendDigitalData(1, true, "yourTopic");

   ```

 

  1. ### `SendAnalogData(int instanceId, float value, string topic)`

 

   Send an analog data type to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `value`: Float value to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   MqttTouchpanelMessenger.SendAnalogData(1, 23.5f, "yourTopic");

   ```

 

  1. ### `SendStringData(int instanceId, string value, string topic)`

 

   Send a string data type to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `value`: String value to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   MqttTouchpanelMessenger.SendStringData(1, "Hello World", "yourTopic");

   ```

 

  1. ### `SendDigitalArray(int instanceId, bool[] values, string topic)`

 

   Send a digital array data type to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `values`: Boolean array to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   MqttTouchpanelMessenger.SendDigitalArray(1, new bool[] {true, false, true}, "yourTopic");

   ```

 

  1. ### `SendAnalogArray(int instanceId, float[] values, string topic)`

 

   Send an analog array data type to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `values`: Float array to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   MqttTouchpanelMessenger.SendAnalogArray(1, new float[] {23.5f, 45.2f, 10.5f}, "yourTopic");

   ```

 

  1. ### `SendSerialArray(int instanceId, string[] values, string topic)`

 

   Send a serial array data type to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `values`: String array to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   MqttTouchpanelMessenger.SendSerialArray(1, new string[] {"First", "Second", "Third"}, "yourTopic");

   ```

 

  1. ### `SendStringDictionary(int instanceId, Dictionary<int, string> value, string topic)`

 

   Send a dictionary containing string values to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `value`: Dictionary with integer keys and string values to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   var stringDict = new Dictionary<int, string> { {1, "Value1"}, {2, "Value2"} };

   MqttTouchpanelMessenger.SendStringDictionary(1, stringDict, "yourTopic");

   ```

 

  1. ### `SendFloatDictionary(int instanceId, Dictionary<int, float> value, string topic)`

 

   Send a dictionary containing float values to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `value`: Dictionary with integer keys and float values to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   var floatDict = new Dictionary<int, float> { {1, 23.5f}, {2, 45.2f} };

   MqttTouchpanelMessenger.SendFloatDictionary(1, floatDict, "yourTopic");

   ```

 

  1. ### `SendBoolDictionary(int instanceId, Dictionary<string, bool> value, string topic)`

 

   Send a dictionary containing boolean values to a specified topic.

 

   **Parameters**:

   - `instanceId`: The unique identifier for the instance.

   - `value`: Dictionary with string keys and boolean values to be sent.

   - `topic`: The MQTT topic to which the message will be published.

 

   **Usage**:

   ```csharp

   var boolDict = new Dictionary<string, bool> { {"Key1", true}, {"Key2", false} };

   MqttTouchpanelMessenger.SendBoolDictionary(1, boolDict, "yourTopic");

   ```

 

### Important Notes:

  1. All the data sending functions utilize the underlying MQTT broker program to publish the data. Ensure the broker is running and the client is properly connected before attempting to send data.
  2. All data is serialized into JSON format using the `Newtonsoft.Json` library before being sent.
  3. While sending arrays or dictionaries, ensure they are properly initialized to avoid null reference exceptions.
  4. Make sure to maintain a consistent topic structure to effectively communicate between devices.

 

### Conclusion:

The `MqttTouchpanelMessenger` class provides an easy-to-use interface to send different data types over MQTT. Properly leverage these functions in your applications for efficient and structured data communication.

Programming In Node Red

About Node Red Events:

Node-RED is designed as a flow-based programming environment, which is event-driven in nature. This means that nodes in Node-RED are triggered when an event occurs, such as receiving a message or detecting a change in the input data. This design choice allows for more flexibility and adaptability when building automation flows and handling various types of data.

In many cases, Node-RED nodes are used to process and transform data, and these nodes often expect input data in the form of messages. Using events to trigger nodes makes it easy to create complex data processing pipelines and integrate with different systems and devices.

 

Why Node Red for AV Programming?

Node-RED is a visual programming tool that allows you to create applications by wiring together various nodes and flows to create control logic. It is primarily used for Internet of Things (IoT) applications and can be run on low-power devices like the Raspberry Pi. With a web-based interface, Node-RED allows users to create flows by dragging and dropping nodes, connecting them, and configuring their properties.

In the context of programming control logic on a Raspberry Pi, Node-RED provides a simple and efficient way to design, develop, and deploy IoT applications. It can be used to connect and control various devices, sensors, and APIs, allowing you to create powerful automation systems and smart home solutions.

When combined with Unity software for front-end UI programming, Node-RED serves as the back-end control logic, while Unity handles the user interface and user experience aspects of the application. Unity is a widely-used game engine and development platform that can create visually appealing and highly interactive user interfaces for various devices and platforms.

By using Node-RED and Unity together, you can build a complete IoT solution with a visually engaging front-end interface and robust back-end control logic. This combination allows you to create applications that can control devices like smart home appliances, monitor and react to sensor data, and provide users with real-time feedback and control over their environment.

In summary, Node-RED is a visual programming tool that simplifies the development of control logic on Raspberry Pi devices. When used alongside Unity for front-end UI programming, it provides a powerful platform for building comprehensive IoT applications with engaging user interfaces and robust back-end control logic.

There are two options for installing the node-red nodes provided by Parallax. 

 

Install by command line:

npm install @parallaxcontrol/node-red-control

Install through the node-red pallet:

 

A list of packages will be installed:

In this example we will go over how to setup the basic flows for sending and receiving messages between the unity touchpanel and node red server.

Here we have 3 partition tabs for organizational purposes.

Tab 1: Mqtt Broker

Contains the Mqtt Broker which handles the connection between the control processor and the touch panel.

Tab 2: TouchPanel

Handles the Inputs and Output signals for the Boolean, Float and String signals.

Tab 3: UiLogic

Handles the logic for the program.

Mqtt Broker Tab:

Add the Aedes node:

How to add a node from the online repository.

Select Manage palette:

Search for the node you want to add:

In this case we add the AEDES MQTT Broker

Drag the node onto the workspace:

Aedes is a lightweight and efficient MQTT broker written in JavaScript for use in Node.js applications, including Node-RED. It enables real-time communication between devices and applications in a distributed network of MQTT-enabled devices, simply by configuring Node-RED's MQTT nodes to use Aedes as the broker.

Configure the Aedes node:

NOTE: Currently Unity only support MQTT V3.1.1 until further updates are available. Be sure to set this in your MQTT output nodes.

The default port for web access is 1880, use port 1883 for programmatic access.

In the Mqtt Broker security tab, enter the credentials which will be required by Mqtt Clients to connect to the broker.

In Unity, add a new Empy GameObject container to the top of your Hierarchy, rename it Processor Connection, drag the ParallaxProcessor script and rename it: 

View the ParallaxProcessor fields in the Unity Inspector:

The Parallax Processor script acts as an Mqtt Client. Enter the correct Mqtt Broker Ip, Port, Username and Password.  

Mqtt Topics To Subscribe To:

To set feedback on the user-interface, subscribe to topics from the program logic. In this case, we have named it digital_Fb, analog_Fb, string_Fb. This means that the user-interface will listen for messages on that topic. 

Mqtt Topics To Publish:

The main 3 topics to publish are Bool, Float, String communication types. The naming of each one is left to the programmer. These are the inputs from the touch-panel that are sent to the back-end logic for processing. The logic can run on either the .net console program, or in node-red. Either way, the logic program has an Mqtt Client which must connect to the Broker and subscribe to the topics it wants to listen to. When the logic program subscribes to the Bool, Float and String topics, it will receive the messages for processing.

How the broker works:

By default, the MQTT broker receives messages from publishing clients and forwards those messages to all clients subscribed to the corresponding topic. The broker itself does not typically subscribe or publish messages. Its primary role is to facilitate message distribution between publishers and subscribers.

TouchPanel Tab:

If using Node Red for logic, you can add an MQTT client node to subscribe and publish to the broker. This means there is an MQTT Broker and MQTT Client running on Node Red. Use the MQTT Client nodes to subscribe to and publish topics. You can use the MQTT In and Out nodes and configure the server and topics accordingly:

The Mqtt Input and Output Nodes come with the Aedes Mqtt Broker. You will need to set the topics to match the topics set in the Unity Mqtt client.

Example configure the input node:

The Server address is the loopback address: 127.0.0.1

The Port is the programmatic access port: 1883

 

UiLogic Tab:

Add a Switch Node. Wire the digital, analog and string inputs to each Switch Node:

NOTE: The payload between the unity touch panel project and node red contains the following properties:

msg.payload.Type
msg.payload.InstanceId
msg.payload.Value

The switch node which will switch on the InstanceId (the unique id for each component in unity).

Configure the switch node property:

msg.payload.InstanceId

This will route the full message (msg.payload) by the InstanceId. From here you can access the Type and Value properties.

 

Click the add button to set the rules:

 

The msg.payload will now output to the associated msg.payload.InstanceId. From here you can access the msg.payload.Type and msg.payload.Value for your logic programming.

 

Current Data Types (msg.payload.Type):

BOOL

FLOAT

STRING

BOOL_ARRAY

FLOAT_ARRAY

STRING_ARRAY

BOOL_DICTIONARY

FLOAT_DICTIONARY

STRING_DICTIONARY

 

 

In the next section we will cover some example usages...

Example: Use the Digital Toggle node to toggle a button press from the unity touchpanel project. In this case we have InstanceId 1 and 2 wired up.

The GetValue node is a helper node that allows the msg.payload.Value to be extracted from the msg.payload object. The output of the GetValue node is a msg.payload. This makes it easy to manipulate the logic. In the above example the GetValue Node drives the Digital Toggle Node with a true value. The Toggle outputs a boolean value to the Set Feedback Node. The Set Feedback node is setup to direct the value to a user specified InstanceId.

Note that the Set Feedback Node simply passes the msg.payload value through to the appropriate InstanceId. You must wire the output of the Set Feedback Node to the appropriate Mqtt Feedback Node.

Custom Logic Nodes

Compare String Node User Guide

The Compare String node is a Node-RED node that allows you to compare a string in the input message with a target string and return a boolean value indicating whether or not they match.

Using the Compare String Node

To use the Compare String node in your Node-RED flow, follow these steps:

  1. Drag the Compare String node from the Node-RED palette and drop it onto the workspace.

  2. Double-click the node to open its configuration panel.

  3. In the configuration panel, you will see the following options:

    • StringToMatch: This is the target string that the input message string will be compared to.
  4. Enter the target string you want to compare with the input message string in the "StringToMatch" field.

  5. Connect the input message to the Compare String node input.

  6. Connect the output of the Compare String node to any downstream nodes that you want to receive the output.

  7. Deploy your Node-RED flow.

Understanding the Compare String Node Output

The Compare String node outputs a boolean value indicating whether the input message string matches the target string.

  • If the input message string matches the target string, the node will output a true boolean value.

  • If the input message string does not match the target string, the node will output a false boolean value.

  • If there is an error, such as when the environment variable StringToMatch is not defined, the node will output an error message object.

Example

Suppose you have a Node-RED flow that receives input messages with a payload that contains a string property named text. You want to compare the value of text to the target string "hello world" and output a boolean value indicating whether or not they match.

Here's how you can use the Compare String node to achieve this:

  1. Drag a Compare String node onto the workspace.

  2. Double-click the node to open its configuration panel.

  3. In the "StringToMatch" field, enter the target string "hello world".

  4. Connect the input message to the node input.

  5. Connect the node output to any downstream nodes that you want to receive the output.

  6. Deploy your Node-RED flow.

Now, when an input message is received, the Compare String node will compare the value of the text property with the target string "hello world". If they match, the node will output a true boolean value. If they do not match, the node will output a false boolean value.

 

Example flow:

In this example, the Compare String Node is used to compare a user-defined value with the input from the touchpanel. If a match is found, the output of the Compare String Node is true, if no match is found, the output is false. In this case, the output of the Compare String Node drives a Digital Toggle Node high or low, then sets the digital feedback on the touchpanel.

Node Name: Digital Toggle

User Guide Summary:

The Digital Toggle node is designed to easily toggle a boolean value and create a message payload with the updated value. This node is helpful for controlling digital outputs or triggering actions based on changing states in your Node-RED flows.

Usage:

  1. Add the Digital Toggle node to your Node-RED flow.
  2. Connect the input and output wires as needed in your flow.

When the node is triggered with a high (true) value, it will toggle the state of the output.

The node then generates a msg.payload containing the updated boolean value.

 

Set/Reset Latch

The Set/Reset Latch node is designed to simulate the functionality of a set/reset latching relay. This node has two outputs. The first output returns the current state of the latching relay, and the second output returns the inverse of the current state.

To use this node, simply send a "SET" or "RESET" message payload to the input. When the "SET" message is received, the latching relay is set to the ON state, and when the "RESET" message is received, the latching relay is set to the OFF state. 

The current state of the latching relay is sent out on the first output, and the inverse of the current state is sent out on the second output. The status of the node will also indicate the current state of the latching relay.

Node Name: Set Digital Feedback

Note: use when you'd like to hardcode the value directly, otherwise see: Set Feedback Node.

User Guide Summary:

The Set Digital Feedback node allows you to create a message payload with a user-selected instance identifier (InstanceId) and a boolean state parameter. It simplifies defining and controlling digital output instances in your Node-RED flows. This node also provides a second output for error handling, which is useful when environment variables are not defined.

Usage:

  1. Add the Set Digital Feedback node to your Node-RED flow.
  2. In the subflow properties, define the following environment variables:
    • InstanceId: Set this to a number representing the instance identifier for the digital output.
    • State: Set this to a boolean value (true/false) representing the desired digital state.
  3. Connect the input and output wires as needed in your flow.

When the node is triggered, it will generate a message payload based on the values of the environment variables "InstanceId" and "State". The payload will be in the following format:

{ "Type": "digital", "InstanceId": instanceId, "Value": state }

Outputs:

  1. Main Output:
    • Sends the digital feedback payload when both environment variables are defined.
    • Sends null when one or both environment variables are not defined.
  2. Error Output:
    • Sends an error message ("One or both of the environment variables (InstanceId, State) are not defined.") when one or both environment variables are not defined.
    • Sends null otherwise.

If one or both environment variables are not defined, the node will output an error message on the second output.

Node Name: Set Analog Feedback

Note: use when you'd like to hardcode the value directly, otherwise see: Set Feedback Node.

 

This user guide explains the functionality, inputs, outputs, and environment variable options for the Set Analog Feedback Node. The purpose of this node is to create and send a message object with a predefined structure containing a type, an instance ID, and a value. The node checks if the required environment variables are defined and sends either the message or an error message to the next connected node in the flow.

Inputs

The Set Analog Feedback Node requires two inputs:

  1. InstanceId: This is an environment variable that represents a unique identifier for a particular instance. To set this value, you must define the InstanceId environment variable in your Node-RED environment.

  2. Value: This is an environment variable that represents the analog value you want to include in the message payload. To set this value, you must define the Value environment variable in your Node-RED environment.

Outputs

The output of the Set Analog Feedback Node depends on whether the required environment variables are defined:

  1. If both environment variables are defined, the node sends a message (msg) with the following structure:
 
{ "Type": "analog", "InstanceId": , "Value": }

Where and are the values of the InstanceId and Value environment variables, respectively. This message is sent to the next connected node in the flow for further processing.

  1. If one or both environment variables are not defined, the node sends an error message with the following structure:
 
{ "payload": "One or both of the environment variables (InstanceId, Value) are not defined." }

This error message is sent to the next connected node in the flow for error handling.

User-Defined Environment Variable Options

There are two environment variables you must define for the Set Analog Feedback Node:

  1. InstanceId: Define this environment variable with a unique identifier for the particular instance you are working with. This identifier will be included in the message payload to distinguish between different instances.

  2. Value: Define this environment variable with the analog value you want to include in the message payload. This value will be passed along with the message for further processing by downstream nodes.

Node Name: Set Serial Feedback  

Note: use when you'd like to hardcode the value directly, otherwise see: Set Feedback Node.

This user guide explains the functionality, inputs, outputs, and environment variable options for the Set Serial Feedback Node. The purpose of this node is to create a message object with a predefined structure containing a type, an instance ID, and a string value. The node then sends the message to the next connected node in the flow.

Inputs

The Set Serial Feedback Node requires two inputs:

  1. InstanceId: This is an environment variable that represents a unique identifier for a particular instance. To set this value, you must define the InstanceId environment variable in your Node-RED environment.

  2. String: This is an environment variable that represents the string you want to include in the message payload. To set this value, you must define the String environment variable in your Node-RED environment.

Outputs

The output of the Set Serial Feedback Node is a single message (msg) with the following structure:

 
{ "Type": "string", "InstanceId": , "Value": }

Where and are the values of the InstanceId and String environment variables, respectively.

This message is sent to the next connected node in the flow for further processing (typically back to the touch panel)

 

User-Defined Environment Variable Options

There are two environment variables you must define for the Set Serial Feedback Node:

  1. InstanceId: Define this environment variable with a unique identifier for the particular instance you are working with. This identifier will be included in the message payload to distinguish between different instances.

  2. String: Define this environment variable with the string value you want to include in the message payload. This value will be passed along with the message for further processing by downstream nodes.

The Set Feedback node

Input: Accepts a msg.payload of type Boolean, String or Int. 

Output: Outputs a msg.payload that drives feedback on the touch panel to the associated instance id.

Configuration: requires a user specified instance id.

Usage: Connect the output to the digital, analog, or string mqtt feedback node. 

AND Gate with Dynamic Inputs

This is a custom Node-RED function node that implements an AND gate with dynamic inputs. The AND gate requires all input values to be true in order to produce a true output. The function node accepts messages with msg.payload and msg.input properties, and maintains the state of the input values across multiple messages.

 

Inputs

msg.payload

This property should be set to a boolean value that represents the input value for the current message. The AND gate requires all input values to be true in order to produce a true output.

msg.input

This property should be set to a number (1-based index) that represents the index of the input value for the current message. 

 

Outputs

The AND gate produces a single output message with a boolean value in the msg.payload property. The output value is true if all input values are true, and false otherwise.

 

Configuration

The AND gate uses a configuration parameter NUM_INPUTS to determine the number of inputs that it should expect. This parameter can be set in the Node-RED environment variables, and defaults to 2 if not set.

 

Example Usage

Example#1

Here's an example flow that uses the AND gate function node to check if all inputs are true: 

In this flow, the inject nodes are used to simulate the input values. The function node is configured with NUM_INPUTS=3 to accept three inputs. The msg.input field identifies the node as a unique input. The debug node is used to display the output value of the AND gate. When all three input values are true, the output value will be true as well. Otherwise, the output value will be false.

 

Example#2

Using the Input Select node.

In this example we use the Input Select node to set the associated input for the AND gate. This way the AND gate can know which input the event came from. This removed the need for adding in the msg.input value as seen on the inject node. Additionally, we set the NUM_INPUTS field in the AND gate to 2, so it knows how many inputs to expect.

Node Name: Or Gate Node 

The Or Gate node is a Node-RED node that performs a logical OR operation on its input messages and outputs a boolean value indicating whether any of the input messages have a payload of true.

Using the Or Gate Node

To use the Or Gate node in your Node-RED flow, follow these steps:

  1. Drag the Or Gate node from the Node-RED palette and drop it onto the workspace.

  2. Connect any input messages that you want to be part of the logical OR operation to the node input.

  3. Connect the output of the Or Gate node to any downstream nodes that you want to receive the output.

  4. Deploy your Node-RED flow.

Understanding the Or Gate Node Output

The Or Gate node outputs a boolean value indicating whether any of the input messages have a payload of true.

  • If any of the input messages have a payload of true, the node will output a true boolean value.

  • If all of the input messages have a payload of false, the node will output a false boolean value.

  • If there is an error, such as when an input message is not received, the node will output an error message object.

 

The Or Gate node updates the msg.payload property with the OR operation result and returns it along with a null value to indicate that there are no errors. The context object is updated with the new input message payloads so that they can be used in the next invocation of the node.

Example

Suppose you have a Node-RED flow that receives input messages from two different sensors. You want to create an Or Gate node that checks if either of the sensors detects an event, and outputs a boolean value indicating whether an event has occurred.

Here's how you can use the Or Gate node to achieve this:

  1. Drag an Or Gate node onto the workspace.

  2. Connect the output of both sensor nodes to the input of the Or Gate node.

  3. Connect the output of the Or Gate node to any downstream nodes that you want to receive the output.

  4. Deploy your Node-RED flow.

Now, when an input message is received from either of the sensors, the Or Gate node will check if either of the messages have a payload of true. If either of the messages have a payload of true, the node will output a true boolean value. If both of the messages have a payload of false, the node will output a false boolean value.

Node Name: Invert Boolean

Description: This node takes a boolean value as input and returns the opposite (inverted) value.

Usage:

  1. Connect the input wire to the input of the Invert Boolean node.
  2. Connect the output wire to the next node in the flow.
  3. Deploy the flow.

Inputs:

  • msg.payload: a boolean value to invert

Outputs:

  • msg.payload: the inverted boolean value

Example Flow:

 
[Inject: true] -> [Invert Boolean] -> [Debug]

In this example flow, the Inject node sends a true value to the Invert Boolean node. The Invert Boolean node inverts the value to false and sends it to the Debug node. The Debug node outputs the inverted value to the debug console.

Notes:

  • This node can be used with any boolean input value (true or false).
  • The input and output values can be of any data type, as long as they can be interpreted as boolean values (i.e. true or false).

 

Inverter Gate:

Example#1:

Using the inject nodes, setup as msg.payload

Node Name:

Get Value Node

 

Configuration:

None

 

Input:

Accepts a msg.payload object

 

Processing:

Extracts the msg.payload.Value property from the msg.payload object.

 

Output:

Outputs a msg.payload with value of type boolean, integer or string.

 

Usage:

The Get Value node is used to extract the msg.payload.Value from the msg.payload object. This contains the boolean, integer or string value sent from the touch panel and allows the programmer to manipulate the logic without needing to write a custom function to parse out the value from the original msg.payload object.

 

The Get Value node connected after the switch node. 

Accepts a msg.payload boolean value.

Outputs the boolean value, along with the specified input selection.

This node allows for dynamic configuration of an input parameter, which is expected to be a number. When a message is passed to this node, it appends this configured input number to the message object as msg.input and then forwards the modified message to its output.

The primary use case of this node is to dynamically tag incoming messages with a specific numeric identifier or selection based on the node's configuration. This can be particularly useful in scenarios where you need to process or route messages differently based on a configurable parameter.

In summary, the node acts as a dynamic tagging mechanism, appending a user-configurable numeric value to each incoming message for further processing down the flow.

## User Manual: Node-RED Dictionary Node

---

### Introduction:

This Node-RED node allows you to create a message payload based on certain environment variables. Specifically, it helps to generate a STRING_DICTIONARY payload with a given instance ID and key-value pair.

When used in conjunction with the DynamicDataArray script in Unity, the programmer can set text values for specific fields based on the element of the object.

---

### Pre-requisites:

- **Node-RED**: Ensure you have Node-RED installed and running.

- **Environment Variables**: This node works by fetching environment variables. Ensure that the required environment variables (`InstanceId`, `Key`, and `Value`) are set before executing this node.

---

### Using the Dictionary Node:

  1. **Add the Dictionary Node to your flow**:

    - Drag and drop the provided Dictionary Node into your Node-RED flow.

  1. **Set the Required Environment Variables**:

    - `InstanceId`: This variable should store the instance ID you want to associate with the message payload.

    - `Key`: This should be the key you want to set in your dictionary payload. When using this node with the DynamicDataArray script in Unity, the key is associated with the element of the item in your list.

    - `Value`: This should be the value associated with the provided key in your dictionary payload.

  1. **Execute the node**:

    - Connect the Dictionary Node to the desired input and output nodes.

    - Deploy your flow and activate the node.

  1. **Observe the output**:

    - If all environment variables are set correctly, the output message (`msg.payload`) will be a structured JSON with the following format:

    ```json

    {

        "Type": "STRING_DICTIONARY",

        "InstanceId": "",

        "Value": {

            "": ""

        }

    }

    ```

    - If there is an issue fetching the environment variables, an error message will be output indicating the specific problem.

---

### Troubleshooting:

- **Error getting environment variables**: This means there was a problem fetching the environment variables. Double-check that the Node-RED environment has the necessary permissions and that the variables are set correctly.

- **Environment variables not defined**: If you see an output message stating that one or more of the environment variables are not defined, make sure that you've set the `InstanceId`, `Key`, and `Value` variables correctly in your environment.

---

### Conclusion:

The Dictionary Node for Node-RED provides a streamlined way to generate dictionary payloads from environment variables. With this node, you can ensure that your flows can dynamically create dictionary payloads based on the given configuration. Make sure to check and set your environment variables correctly to get the desired outputs.

SAMPLE USAGE:

When paired with the DynamicDataArray script, the SendStringDictionaryPayload can populate each element of the list with the values from the dictionary.

For instance, in this 0-based list, a Key value of "0" corresponds to the first element, this TextMeshPro Object will be dynamically populated with the text "hello". 

Snippet from the Dynamic Data Array script.

The Dynamic Data Array script is setup to look for the InstanceId, as well as the Data Type; in this case String Dictionary. The Tag to Match In Prefab is used to match the TextMeshPro objects which are tagged only, and ignores TextMeshPro objects which are not tagged in the prefab. 

## User Manual: Node-RED Dictionary Node

## User Manual: Node-RED SendBoolDictionary Node

---

### Introduction:

The SendBoolDictionary Node in Node-RED facilitates the generation of a message payload constructed from predefined environment variables. This node is designed to produce a BOOL_DICTIONARY payload with a specified instance ID and key-value pair.

---

### Pre-requisites:

- **Node-RED**: Make sure you have Node-RED set up and operational.

- **Environment Variables**: This node operates by obtaining environment variables. Thus, you need to ensure that the necessary environment variables (`InstanceId`, `Key`, and `Value`) are predefined prior to deploying this node.

---

### How to Use the SendBoolDictionary Node:

  1. **Integrate the SendBoolDictionary Node into your flow**:

   - Incorporate the SendBoolDictionary Node into your Node-RED workflow by dragging and positioning it.

  1. **Define the Essential Environment Variables**:

   - `InstanceId`: This variable should signify the instance ID you wish to be associated with the message payload.

   - `Key`: This is the key you intend to establish in your dictionary payload.

   - `Value`: This represents the corresponding value of the assigned key in your dictionary payload.

  1. **Run the node**:

   - Link the SendBoolDictionary Node to the preferred input and output nodes.

   - Deploy your workflow and initiate the node.

  1. **Inspect the Result**:

   - Given all environment variables have been correctly configured, the output message (`msg.payload`) will emerge in this structure:

    ```json

    {

        "Type": "BOOL_DICTIONARY",

        "InstanceId": "",

        "Value": {

            "": ""

        }

    }

    ```

   - If any complications arise during the retrieval of the environment variables, a corresponding error message will elucidate the specific concern.

---

### Troubleshooting:

- **Encountering Errors Retrieving Environment Variables**: If this scenario arises, it indicates a potential complication in fetching the environment variables. Confirm that Node-RED's environment possesses the appropriate permissions and that the variables are aptly set.

- **Undefined Environment Variables**: If you observe an output signifying the non-definition of one or more of the environment variables, it's crucial to ascertain that you've accurately set the `InstanceId`, `Key`, and `Value` variables in your environment.

---

### Conclusion:

The SendBoolDictionary Node for Node-RED is a robust solution for dynamically generating BOOL_DICTIONARY payloads anchored on environmental configurations. By ensuring accurate setting and permission grants for environment variables, you can exploit this node to the fullest and streamline your Node-RED flows.

 

EXAMPLE USAGE:

When paired with the DynamicDataArray script, the SendBoolDictionaryPayload can populate each element of the list with the values from the dictionary.

For instance, in this 0-based list, a Key value of "1" corresponds to the second element, the Button object will be set with the value of 1, signal high. The Value will be set with the value True.

 

 

## User Manual: Node-RED SendFloatDictionaryPayload Node

---

### Introduction:

The SendFloatDictionaryPayload Node is specifically designed for Node-RED, which aids in constructing message payloads rooted in predefined environment variables. Tailored for the creation of a FLOAT_DICTIONARY type payload, this node outputs a payload with an instance ID alongside the specified key-value pairing.

---

### Pre-requisites:

- **Node-RED Installation**: Ensure you have Node-RED set up and actively running on your system.

- **Environment Variables Configuration**: This node operates based on the retrieval of certain environment variables. Ensure `InstanceId`, `Key`, and `Value` are pre-configured before deploying this node.

---

### Node Operation:

1. **Node Integration**:
- Insert the SendFloatDictionaryPayload Node into your Node-RED flow by dragging and dropping it into the desired position.

2. **Environment Variables Configuration**:
- `InstanceId`: Defines the unique ID for the instance you're associating with the payload.
- `Key`: Specifies the dictionary key for your payload.
- `Value`: Assigns the corresponding value associated with the defined key in the dictionary payload.

3. **Node Execution**:
- Connect the SendFloatDictionaryPayload Node to appropriate input and output nodes.
- Deploy your flow and initiate the node operation.

4. **Output Evaluation**:
- With all environment variables set correctly, your output message (`msg.payload`) will appear as:

```json
{
"Type": "FLOAT_DICTIONARY",
"InstanceId": "",
"Value": {
"": ""
}
}
```

- If there are issues retrieving the environment variables, an error message will be provided detailing the problem.

---

### Troubleshooting:

- **Environment Variables Retrieval Error**: If this arises, it indicates a problem accessing the environment variables. Ensure Node-RED has the required permissions and that the variables (`InstanceId`, `Key`, and `Value`) are set appropriately.

- **Environment Variables Undefined Error**: If you're alerted that one or more environment variables are undefined, verify the correct configuration of `InstanceId`, `Key`, and `Value` within Node-RED's environment.

---

### Conclusion:

With the SendFloatDictionaryPayload Node in Node-RED, generating FLOAT_DICTIONARY payloads based on environmental configurations becomes seamless. Ensure all necessary environment variables are set correctly to capitalize on the efficiency and utility of this node within your Node-RED flows.

 

Sample Usage:

When paired with the DynamicDataArray script, the SendFloatDictionaryPayload can populate each element of the list with the values from the dictionary.

For instance, in this 0-based list, a Key value of "1" corresponds to the second element, this TextMeshPro Object will be dynamically populated with the text "hello". 

MQTT

  • In MQTT, when the Retain flag is set to True for a message on a topic, the broker retains only the latest message for that topic. When a new client subscribes to the topic, the broker sends this retained message to the client. It's important to note that only one message per topic is retained

Interfacing with Third Party Control

Send commands to the Parallax Control System using the Tesira Command String block:

Tesira software offers powerful logic programming options on its own, but for more advanced logical operations, its possible to send a simple command to the Parallax processor to trigger additional automation sequences to run. In this section we will show you how to send commands from the Tesira DSP to the Parallax Control Processor.

Tesira software allows for the creation of a Command String block that is network based.  This allows the user to configure the block within a Tesira device to transmit text strings over TCP or UDP to a defined network server address. This communication can be referred to as 'Unsolicited Communication' meaning that the Client device sends information to the Server device without the Server device requesting the information.

The goal of this document is to provide a basic example of deploying the Tesira Network Command String Block with a Parallax control processor acting as the Server.

 

Tesira Setup

The first step will be to drop in the Command String block with Tesira software.  Select the necessary number of strings when presented with the following dialog and the matching block will be created.

 

 

 

Next, we'll need to populate the block Properties with the appropriate information.  Note that the Server Address and Remote Port defines the target to which strings will be sent.

 

 

The Network Command String block will only send when it receives a logic high input so we'll need to connect some logic inputs.

 

 

Additionally, we'll need to define the strings we want sent.

 

Server Setup: Parallax Control Processor

Within the Node Red program, one or multiple TCP/IP Servers will need to be setup.  By setting the Default IP Address to 0.0.0.0 we allow the Server to receive connections from any (Client) IP address.  Keep in mind that this Server needs to be online so that the Tesira Network Command String block (Client) can send strings to it.

 

Drag the Tcp In Node to the canvas:

 

In the Edit Tcp In Node view, the TCP/IP port needs to be defined. In this example, we are using port 65534. Additional signals will need to be created and connected within the Parallax program based upon the project needs.

 

 

Add the switch node, along with debug nodes to read the output.

 

 

Configure the switch node to match the incoming strings:

 

 

In Tesira trigger one of the command strings, it will show in the debug section. With this you can use the logic to drive additional programming as required.

 

 

Test the Tcp in node locally without building a Tesira File:

To test this without building a tesira file, simply drop in a tcp out node and an inject node:

Configure the inject node:

Configure the Tcp out node:

 

Using UDP

To enable UDP communication, simply replace the Tcp nodes with the associated Udp nodes:

 

 

 

 

 

 

 

In this example we will show how to setup a Crestron IP Client (TCP or UDP) to send and receive commands between a Crestron Processor and the Parallax Control Processing using Node Red. 

Crestron Setup

Add a TCP/IP Client symbol and Serial I/O symbol. In this example we are going to use port 65534. A delimiter of \x0d is used in the Serial I/O to denote the end of the message. This logic will attempt to connect to the Parallax processor on startup and send the message "hello from crestron" as soon as the TCP connection is made.

Configure the TCP/IP Client symbol with the ip address of the Parallax Control Processor:

Parallax Control setup:

Drop in the Tcp in node and connect a debug node to read the output. Set the port to listen onto 65534.

The message is received and printed to the debug log. 

Device Info

The Parallax Control Processor device is accessible by hardwired ethernet, or by its on-board access point. 

The access point default SSID is: CM4-'serialnumber'

Default password: 'macaddress'

 

Once connected to the AP, open a terminal window and ssh into the device:

ssh pi@

-or-

ssh [email protected]

 

Note: if you receive a connection warning, you may need to delete/modify your known hosts file on your computers hidden .ssh folder.

WIRELESS ACCESS POINT AND ETHERNET PORT CONSIDERATIONS:

The on-board access point contains a router with DHCP server. The controller is set to hand out DHCP addresses to devices connecting via the onboard access point, such as your laptop or a wireless touch panel. Currently, these devices will be given an address on the 192.168.10.0 subnet, which must remain different from the wired nic subnet.

The controllers ethernet port is by default set as DHCP. If no DHCP server is preset, it will revert to a link local address. 

Note: All hardwired ethernet devices which are to be controlled, should be set with static addresses. The controllers ethernet nic does not contain a dhcp server. Be sure to set the control processor, and the devices to control on the same subnet. Note wireless touch panels, if connected by the on-board access point will be able to communicate with devices on the wired nic.

 

Managing Device from Access Point: You may connect directly to the on-board ap to load code and manage the device the same as if you set up a wired network. This is very convenient for programmers as they can update projects wirelessly.

Enter the ip address of the device into the web browser.

Please note, the system by default is set to DHCP, and will need an address to be set by the network.

Default Password: The default password is the mac address of the device, with no colons, all lower-case. The login button will bring you to the device control page.

Node Red Dashboard: Select node red to be directed to the node red dashboard.

username: admin

password: <macaddress>

Node red dashboard can be used to quickly test, or to write full logic control.

RTSP Decoder: Outputs the rtsp stream to the full-size HDMI port.

USB Camera Encoder: Encodes usb webcam and transmits over the network. Set the stream name so decoders can subscribe to the stream.

USB Camera Decoder: Set the stream name and enable the decoder to decode and display the stream out of the hdmi port.

Persist on reboot: determines if the current settings should be maintained if the device reboots.

Note: transmission delay between encoder and decoder is about half a second, and is not currently recommended for use in live events.

Upload Video: upload multiple videos to the device. 

Choose: choose which video to play out the full-size hdmi port.

Note: Currently supports 1080p playback.

Delete folder contents: clears the program upload folder.

Load Program: transfers the binary executable file to the program folder.

Allow Permission: allows the newly transferred binary executable file to be executable.

Stop Program: stops the current program.

Start Program: starts the program.

Restart: reboots the control processor.

Device Info: shows the current info for the device.

Network Settings: The default setting is DHCP. This section allows for changing between DHCP or Static addressing.

Mode: toggles between DHCP and Static.

Static Router: allows changing of the static router.

Domain Name Servers: allows changing of the dns.

Hide Access Point SSID: when checked, disables the access point ssid from being shown on wifi scans.

Device IO Wiring Guide

Analog To Digital

Analog to digital conversion is currently under development. Available in a future release.

CM4-Pro has two channels of digital input detection with isolation. There are only two states of
digital input: high level and low level. There are two connection methods for digital input signals, namely
dry contact (passive) connection and wet contact (active) connection.

Wet Contact
The connection mode of wet contact needs external power supply, the input is active signal, the positive
electrode is connected to the DIN+ port of equipment, and the negative electrode is connected to the
DIN- port of equipment. When DIN+ and DIN- are connected and the level signal is greater than 3V, the
internal optical coupler of DI port is connected, that is, the module considers the input signal as low level;
when DIN+ and DIN- are disconnected, the internal optical coupler of DI port is connected, that is, the
module considers the input signal as high level.

 

In the field of industrial control, three wire PNP type and NPN type sensors are the most common.
Among the three wires, usually brown represents the positive electrode (VCC), blue represents the
negative electrode (GND), and black represents the signal output terminal (OUT).
PNP type sensors are also known as source input mode sensors. When a signal is triggered, the OUT
signal terminal outputs a high level.
The connection diagram of PNP type sensor is as follows.

If you do not use an external power supply to power the sensor, you can use the Vout provided by CM4
Industrial for power supply. The connection diagram for PNP type sensors using Vout power supply is as
follows:

WARN: Vout can only provide 12V power output.
NPN type sensors are also known as sinking input mode sensors. When a signal is triggered, the OUT
signal terminal outputs a low level.
The connection diagram of NPN type sensor is as follows.

If you do not use an external power supply to power the sensor, you can use the Vout provided by CM4
Industrial for power supply. The connection diagram for NPN type sensors using Vout power supply is as
follows:

WARN: You can only provide 12V power output.

Dry Contact
The input signal of dry contact connection mode is passive switching signal. The change of input state
can be detected by disconnecting or shorting the DI and COM port.

Relay
Relay output interfaces NC, COM and NO correspond to normally closed, common interface and
normally open relay respectively. The relay on board CM4 Industrial is a double-pole, double-throw relay.
When the control relay is closed, NO1 and NO2 are closed relative to COM1 and COM2, and when the
control relay is bounced off, NO1 and NO2 are open relative to COM1 and COM2.

 

RS232
CM4 Industrial has a serial port with standard RS232.
The wiring diagram of RS232 serial port is as follows:

CM4 Industrial has two RS485 channels.
Taking RS485-1 interface as an example, the wiring diagram is as follows:

Flashing eMMC (Service Only)

eMMC stands for "embedded MultiMediaCard" and is a type of non-volatile storage device used in computing systems, including the Raspberry Pi Compute Module 4 (CM4).

The Raspberry Pi CM4 features a built-in eMMC storage option in addition to the standard SD card slot. The eMMC storage is a flash memory technology that is soldered directly onto the CM4 module and offers a reliable and fast storage solution for embedded applications.

Compared to SD cards, eMMC storage typically has faster read and write speeds, higher endurance, and more robust wear-leveling algorithms. It also eliminates the need for a separate SD card, which can be advantageous in space-constrained designs.

The CM4 comes in different variations, some with eMMC storage and some without. The eMMC versions of the CM4 offer 8GB, 16GB, or 32GB of storage, depending on the model, and can be a good choice for applications that require reliable and fast on-board storage.

 

The operating system is flashed to the eMMC. This is also where all control programs reside.

 

Note: It is not necessary to flash the eMMC unless directed to do so by a Parallax Factory Authorized Support Specialist. This is typically done to reinstall the operating system, and to re install the parallax control engine.

Note: Flashing the CM4-NANO eMMC should only be done with the guidance of a Parallax Control Support Specialist. Contact support if your device requires a fresh operating system installation.

CM4-NANO Flash Setup:

Step 1.

Unplug the power.

Step 2.

Using a USB-A to USB-A cable, connect one end to your computer, the other end to the USB 2.0 port on the CM4-Nano (the white usb port)

Step 3.

Switch the device into boot mode (or short the pins).

Step 4.

Power on the CM4-Nano.

Step 5.

Using the CLI on your computer, execute the rpi tool as follows:

Run the rpi boot tool:

"./rpiboot"

Below shows the result:

Next, start up pi imager, under Operating System, select "raspberry pi os lite (32-bit)". Under Storage, select the eMMC.

Open the settings wheel to set your configuration as follows:

Hostname: cm4-'macaddress'

Enable SSH: Password Auth

Set Username and password:

user: pi

password: 'macaddress'

Set appropriate Locale settings 

Save and Write.

Once Pi Imager completes, unplug the power to the CM4-NANO, remove the usb cable and remove the wire used to short the boot pin.

Wait 5 seconds and power on the CM4-NANO.

The CM4-NANO should now be ready for ssh login.

Next, ensure the device has internet access, you can confirm by using: "ping 8.8.8.8". 

Once its been confirmed the device has internet access, the Parallax support specialist will confirm your license and supply a link which will be used to automatically install the latest version of the Parallax Control Engine.

Instructions To install the RPI Boot Tool on a mac:

To install the Raspberry Pi (RPi) boot tool on a Mac, you can use the Terminal and Homebrew package manager to install the rpiboot package. Here are the steps to do this:

  1. Open the Terminal application on your Mac. You can find it in the "Utilities" folder within the "Applications" folder.
  2. Install Homebrew package manager by running the following command in the Terminal:
     
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

    This will download and install Homebrew on your Mac.

  3. Install USB Boot tool for macOS

    From a macOS machine, you can also run usbboot, just follow the same steps:

    • Clone the usbboot repository
    • Install libusb (brew install libusb)
    • Install pkg-config (brew install pkg-config)
    • (Optional) Export the PKG_CONFIG_PATH so that it includes the directory enclosing libusb-1.0.pc
    • Build using make
    • Run the binary
    git clone --depth=1 https://github.com/raspberrypi/usbboot
    cd usbboot
    brew install libusb
    brew install pkg-config
    make
    sudo ./rpiboot
  4. Connect your Raspberry Pi to your Mac using a USB cable.
  5. Power on the Raspberry Pi.
  6. In the Terminal, run the following command to start the rpiboot tool:
     
    sudo ./rpiboot

    This will start the boot tool and allow your Mac to access the Raspberry Pi's file system.

You can now access the Raspberry Pi's file system from your Mac and perform tasks like installing the operating system or transferring files. To exit the rpiboot tool, press Ctrl-C in the Terminal.