Coreflux C# Digital Worker Asset

Hugo Vaz
Coreflux Blog
Published in
13 min readMar 5, 2023
Inside the Asset 😅

The Digital Worker Asset is a powerful tool designed to help developers run C# code with the ability to connect to MQTT topics in a data hub made with Coreflux. It provides an easy way to create and deploy custom code that can interact with data from IoT devices, sensors, and other sources in real time.

The Digital Worker Asset C# is handy for industrial automation, smart energy and other applications that require real-time data processing, as it allows developers to quickly write and execute code that can react to changes in data and trigger actions accordingly. This can be used to implement advanced monitoring, control, and automation functions that can help optimize operations and reduce costs.

Some of the key features of the Digital Worker Asset include:

  • Support for C# code execution
  • Ability to connect to MQTT topics in Coreflux and outside Coreflux
  • Feedback on executions
  • Easy scalable deployment
  • MQTT Compatibility can run in other infrastructures already

The Digital Worker Asset is an essential tool for developers looking to create powerful, scalable and efficient IoT solutions using Coreflux. It allows them to quickly write and execute custom code that can interact with data from IoT devices, sensors, and other sources in real-time, helping them to build advanced monitoring, control, and automation functions that can improve operations and reduce costs by creating a Hybrid System.

The Hybrid System Approach

One of the main advantages of a Hybrid System is the ability to leverage the benefits of both on-premises and cloud resources. On-premises resources are typically closer to the edge devices, which can help to reduce latency and ensure more reliable communication. Meanwhile, cloud resources provide scalability, flexibility, and cost efficiency. By combining the two, developers can create a powerful and efficient system that can handle real-time data processing, storage, and analysis.

A Hybrid System can also help to address the security and compliance concerns that often arise with IoT solutions. By storing sensitive data on-premises and using cloud resources for non-sensitive tasks, developers can create a more secure and compliant system that meets the needs of their organization.

Additionally, an Hybrid System can reduce costs by optimizing resource usage. On-premises resources can be used for critical tasks that require low latency, while cloud resources can be used for less critical functions that can be offloaded to the cloud for cost savings.

Overall, an Hybrid System can provide a range of benefits for IoT solutions, including improved performance, security, compliance, and cost efficiency. By leveraging the power of both on-premises and cloud resources, developers can create a system that meets the unique needs of their organization and delivers real business value.

Example

This is a typical integration of Coreflux that can help save up to 87% of subscription fees in many cases, depending on the cloud provider, architecture, and data ratio. In this scenario, the OT MQTT brokers are close to the edge devices, providing real-time data at milliseconds and second intervals. The IT MQTT broker contextualizes and aggregates the data into higher-level information, which is then sent to the cloud for analysis. By combining the power of on-premises and cloud resources, you can create a system that meets your organization’s unique needs while minimizing costs.

Overall, this example highlights the benefits of a Hybrid System for industrial IoT solutions, including improved performance, reduced costs, and optimized resource usage. By leveraging the power of both on-premises and cloud resources, you can create a system that delivers real business value while meeting your organization’s unique needs.

C# — The Natural Language of this Digital Worker

C# (pronounced “see-sharp”) is a modern, object-oriented programming language developed by Microsoft. It was introduced in 2000 and is used to build a wide range of applications for Windows, web, and mobile platforms. C# is a popular choice for developing enterprise applications due to its ease of use, robustness, and scalability.

To give you a sense of what C# code looks like, here’s an example of a simple console application that counts numbers:

using System;
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
}
}

In this code, we first import the System namespace, which contains a set of useful classes and functions that we can use in our program. Then, we define a class called Program, which contains a static method called Main. The Main method is the entry point of our program, which gets executed first when we run the program.

Inside the Main method, we use a for loop to count from 0 to 9, and for each number, we print it to the console using the Console.WriteLine method. Finally, we exit the program.

This is just a simple example to give you a taste of C# syntax. In practice, C# can be used to build much more complex applications.

So how to make a Code for a C# Digital Worker Asset

To prepare the code for the Digital Worker C# asset using Visual Studio Code, you’ll need to follow these steps:

Install Visual Studio Code: If you haven’t already, download and install Visual Studio Code, which is a lightweight, cross-platform code editor that supports a wide range of programming languages, including C#.

Create a new C# project: Open Visual Studio Code and create a new C# project by selecting “File” -> “New File” -> “C#” from the menu. Choose a name and location for your project and click “Create”.

Write your code: Open the program.cs file in your project and write your C# code.

To get a better perspective we will use an example. We want to have a counter of parts in a production process of a machine. The program will run continuously and check the status of two tags, “MachineOn” and “ProductionOn”. If both tags are set to “true”, the program will increment a counter of parts and write the new count to the “Count” tag. If the “ProductionOn” tag is set to “false”, the program will reset the ProductionLast boolean to false. The program will also pause for one second before checking the tags again.

The Concept:

How To Count Parts with a PLC Signal

The Editor with the code :

Using Visual Studio CGA Style 👴

The Code:

using System;
using Coreflux.DigitalWorker;
using System.Threading;
namespace EdgeCountingPartss
{
class Program
{
static void Main(string[] args)
{
int i = 0;
bool ProductionLast=false;

while (true)
{
if(TagHolder.Read("MachineOn").Equals("true") && TagHolder.Read("ProductionOn").Equals("true"))
{
if(ProductionLast==false)
{
i++;
Console.WriteLine(i.ToString());
TagHolder.Write("Count",i.ToString());
Thread.Sleep(1000);
ProductionLast=true;
}
else
{
//do nothing
}
}
if(TagHolder.Read("ProductionOn").Equals("false"))
{
ProductionLast=false;
}
}
}
}
}

So we have the code, let’s configure our asset.

Configuration of the asset using Commands

Check the asset list topic to obtain the GUID of the Digital Worker Asset you wish to configure. Topic -> $SYS/Coreflux/Assets

The Topic $SYS/Coreflux/Assets

Use a text editor to create a JSON configuration for the Digital Worker asset, or modify an existing configuration file as needed. The JSON configuration should include values for the parameters you wish to set, such as the mqttPort, mqttAddress, and CycleTime. Use the AssetHelp Command to get a standard config.

Use the assetConfigSave command to save the JSON configuration to the Digital Worker asset. The topic to provide the config is $SYS/Coreflux/Cloud/Command.

The syntax for the command is as follows:

-assetConfigSave <guid> <configuration>

Replace <guid> with the GUID of the Digital Worker Asset, and <configuration> with the contents of your JSON configuration file.

For example, if your Digital Worker asset has a GUID of 12345678–9abc-def0–1234–56789abcdef0 and your JSON configuration file is named DigitalWorkerConfig.json, you would copy the contents of the file and use the following command:

assetConfigSave 12345678–9abc-def0–1234–56789abcdef0 {
"MqttClient": {
"mqttPort": 1883,
"mqttAddress": "127.0.0.1",
"isAnonymous": true,
"username": "root",
"password": "coreflux",
"withTLS": false,
"DebugTopicEnabled": false,
"DebugTopic": null
},
"DigitalWorker": {
"CycleTime": 100,
"ConsoleTopicFeedback": "Coreflux/DigitalWorker/console",
"ErrorTopicFeedback": "Coreflux/DigitalWorker/error"
},
"tags": [
{
"name": "Test DigitalWorker",
"code": "
using System;
using Coreflux.DigitalWorker;
using System.Threading;
namespace Test {
class Program {
static void Main(string[] args)
{
int i = 0;
bool ProductionLast=false;
while (true)
{
if(TagHolder.Read(\"MachineOn\").Equals(\"true\")
&& TagHolder.Read(\"ProductionOn\").Equals(\"true\"))
{
if(ProductionLast==false) {
i++;
Console.WriteLine(i.ToString());
TagHolder.Write(\"Count\",i.ToString());
Thread.Sleep(1000);
ProductionLast=true; }
if(TagHolder.Read(\"ProductionOn\").Equals(\"false\"))
{
ProductionLast=false;
}
}
}
}
}"
}
]
}

The Digital Worker asset should now be configured with the new settings. You can use the assetConfigLoad command to confirm that the configuration has been applied correctly. Go to the topic $SYS/Coreflux/Cloud/Command and:

//assetConfigLoad <theAssetGuid> 
//in this example:
assetConfigLoad 12345678–9abc-def0–1234–56789abcdef0

You should get the configuration of the asset. Start the asset by using the command in topic $SYS/Coreflux/Cloud/Command :

-R 12345678–9abc-def0–1234–56789abcdef0

Check the Runtime

Since the Digital Worker Asset has a topic to show everything that writes in the console you can check the topic. In this config, it is Coreflux/DigitalWorker/console. If all is well the digital worker should compile all tags, which are code to run scripts.

The Console of the Digital Worker
The feedback in our DataHub

In this example, we had to change the MachineOn to true and the ProductionOn to true as well.

If the device changes the MachineOn to true and the ProductionOn we get a Count. Since we have it in our code Console.WriteLine the console topic reacts to our write line command and shows the string.

Magic🧙‍♂️

Now, you can send that count to the cloud, providing an injection of information instead of just data. Since the Production Counter and Machine State are signals, the system would need to store and keep up with them at low latency, which can result in higher cloud costs.

Potential Usage

The Digital Worker Asset provides users with the ability to create custom scripts that can contextualize and process data on an IIoT platform. By leveraging the power of C#, users can create sophisticated scripts that can perform complex calculations, manipulate data, and interact with other components of the platform.

Some examples of scripts that can be created using the Digital Worker Asset include:

Data transformation scripts: These scripts can be used to transform raw data into a format that is more meaningful or useful for downstream applications. For example, a script could be created to convert temperature readings from Fahrenheit to Celsius, or to aggregate data from multiple sensors into a single output.

Example Concept
{
"MqttClient": {
"mqttPort": 1883,
"mqttAddress": "127.0.0.1",
"isAnonymous": true,
"username": "root",
"password": "coreflux",
"withTLS": false,
"DebugTopicEnabled": false,
"DebugTopic": null
},
"DigitalWorker": {
"CycleTime": 100,
"ConsoleTopicFeedback": "Coreflux/DigitalWorker/console",
"ErrorTopicFeedback": "Coreflux/DigitalWorker/error"
},
"tags": [
{
"name": "Temperature Conversion",
"code": "
using System;
using Coreflux.DigitalWorker;
using System.Threading;
namespace Test
{
class Program
{
static void Main(string[] args)
{
while (true)
{
var tempF = double.Parse(TagHolder.Read(\"sensor/temperatureinF\"));
var tempC = (tempF - 32) * 5 / 9;
TagHolder.Write(\"sensor/temperatureinC\", tempC.ToString());
Thread.Sleep(1000);
}
}
}
}"
}
]
}

Predictive analytics scripts: These scripts can be used to analyze historical data and make predictions about future events or trends. For example, a script could be created to analyze the performance of a machine over time and predict when it will require maintenance.

Control scripts: These scripts can be used to control the behaviour of other components of the IIoT platform. For example, a script could be created to turn off a machine if it detects an abnormal condition, or to adjust the settings of a sensor based on environmental conditions.

assetConfigSave 12345678-9abc-def0-1234-56789abcdef0 {
"MqttClient": {
"mqttPort": 1883,
"mqttAddress": "127.0.0.1",
"isAnonymous": true,
"username": "root",
"password": "coreflux",
"withTLS": false,
"DebugTopicEnabled": false,
"DebugTopic": null
},
"DigitalWorker": {
"CycleTime": 100,
"ConsoleTopicFeedback": "Coreflux/DigitalWorker/console",
"ErrorTopicFeedback": "Coreflux/DigitalWorker/error"
},
"tags": [
{
"name": "ControlScript",
"code": "
using System;
using Coreflux.DigitalWorker;
using System.Threading;
namespace ControlScripts
{
class Program
{
static void Main(string[] args)
{
while (true)
{
double temperature = Double.Parse(TagHolder.Read(\"sensor/temperature\"));
if (temperature > 80) {
TagHolder.Write(\"machineOn\", \"false\");
}
Thread.Sleep(5000); // Wait 5 seconds before checking temperature again
}
}
}
}"
}
]
}
An example of a stop of a system!

Reporting scripts: These scripts can be used to generate reports or alerts based on data collected by the IIoT platform. For example, a script could be created to generate a daily report of production metrics or to send an alert if a sensor reading exceeds a certain threshold. For example a JSON object.

Here’s an example of a reporting script that generates a daily report of the number of times the temperature exceeds 100 degrees Fahrenheit. The report is stored as a JSON object in Coreflux in a Topic in these case Coreflux/Reports/DailyReport!

using System;
using Coreflux.DigitalWorker;
using System.Threading;
using System.Collections.Generic;
namespace Reporting {
class Program {
static void Main(string[] args) {
string reportTopic = "Coreflux/Reports/DailyReport";
Dictionary<string, int> reportData = new Dictionary<string, int>();

while (true) {
double temperature = double.Parse(TagHolder.Read("sensor/temperatureinF"));
if (temperature > 100.0) {
DateTime timestamp = DateTime.UtcNow;
string date = timestamp.Date.ToString("yyyy-MM-dd");
if (!reportData.ContainsKey(date)) {
reportData[date] = 0;
}
reportData[date]++;
}

Thread.Sleep(10000); // wait for 10 seconds before checking temperature again

// Generate and store daily report
if (DateTime.UtcNow.TimeOfDay >= new TimeSpan(23, 59, 59)) {
string report = "{";
report += "\"timestamp\": " + DateTimeOffset.UtcNow.ToUnixTimeSeconds() + ",";
report += "\"data\": {";
foreach (KeyValuePair<string, int> entry in reportData) {
report += "\"" + entry.Key + "\": " + entry.Value + ",";
}
report = report.TrimEnd(',');
report += "}";
report += "}";

TagHolder.Write(reportTopic, report);
reportData.Clear();
}
}
}
}
}

The Digital worker can seamlessly store and run up to 15 scripts!

So let’s make a real-life example for a digital worker asset, to provide an OT/IT integration for a hot water pump based on the temperature of the water. Using the data conversion script, we convert the temperature reading from Fahrenheit to Celsius, which is then used by the control script to turn on or off the pump in case of an excess in temperature. The reporting script collects temperature readings every 10 seconds and generates a message reporting that already 10 times the temperature exceeded 85 degrees Celsius.
This way we have a very simple contextualization of a specific parameter, in this case, temperature.

The configuration of everything together:

assetConfigSave 12345678-9abc-def0-1234-56789abcdef0 {
"MqttClient": {
"mqttPort": 1883,
"mqttAddress": "127.0.0.1",
"isAnonymous": true,
"username": "root",
"password": "coreflux",
"withTLS": false,
"DebugTopicEnabled": false,
"DebugTopic": null
},
"DigitalWorker": {
"CycleTime": 100,
"ConsoleTopicFeedback": "Coreflux/DigitalWorker/console",
"ErrorTopicFeedback": "Coreflux/DigitalWorker/error"
},
"tags": [
{
"name": "DataConversion",
"code": "
using System;
using Coreflux.DigitalWorker;
namespace DataConversion {
class Program {
static void Main(string[] args)
{
while (true)
{
double temperatureInF = Convert.ToDouble(TagHolder.Read(\"sensor\\temperatureinF\"));
double temperatureInC = (temperatureInF - 32) * 5 / 9;
TagHolder.Write(\"sensor\\temperatureinC\", temperatureInC.ToString(\"0.00\"));
System.Threading.Thread.Sleep(1000);
}
}
}
}"
},
{
"name": "ControlScript",
"code": "
using System;
using Coreflux.DigitalWorker;
namespace ControlScript {
class Program {
static void Main(string[] args)
{
while (true)
{
if (TagHolder.Read(\"sensor\\temperatureinC\") > \"100\")
{
TagHolder.Write(\"pump\\onoff\", \"0\");
}
else
{
TagHolder.Write(\"pump\\onoff\", \"1\");
}
System.Threading.Thread.Sleep(1000);
}
}
}
}"
},
{
"name": "ReportingScript",
"code": "
using System;
using System.Collections.Generic;
using Coreflux.DigitalWorker;
namespace ReportingScript {
class Program {
static void Main(string[] args)
{
List<double> temperatures = new List<double>();
while (true)
{
double temperatureInC = Convert.ToDouble(TagHolder.Read(\"sensor\\temperatureinC\"));
if(temperatureInC> 85)
{
temperatures.Add(temperatureInC);
}
if (temperatures.Count >= 10)
{
string report = \"{\\\"timestamp\\\": \" + DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() + \", \\\"count\\\": \" + temperatures.Count.ToString() + \"}\";
TagHolder.Write(\"reporting\\dailytemperature\", report);
temperatures.Clear();
}
Thread.Sleep(10000);
}
}
}
}"
}
]
}

Overall, the Digital Worker Asset provides users with a tool for contextualizing and processing data on an IIoT platform. By leveraging the flexibility and power of C#, users can create custom scripts that meet their specific needs and add value to their organization.

TagHolder

The TagHolder is a class provided by the Digital Worker Asset that allows you to interact with Coreflux tags using C# code. The TagHolder provides three main functions: TagHolder.Init, TagHolder.Read, and TagHolder.Write.

To interact with the Coreflux data hub, you can use TagHolder to read and write tags.

TagHolder.Init is used to initialize a tag for reading. Once a tag has been initialized, you can use TagHolder.Read to read the tag’s payload and TagHolder.Write to write a payload to the tag.

TagHolder.Read takes a tag name as its argument and returns the payload of that tag as a string. If the tag has not been initialized using TagHolder.Init, TagHolder.Read will return an empty string.

// initialize tag
TagHolder.Init("my-topic");

// read tag payload
string payload = TagHolder.Read("my-topic");

// print payload to console
Console.WriteLine("Tag payload: " + payload);

TagHolder.Write takes a tag name and a payload as its arguments and writes the payload to the specified tag. If the write operation is successful, TagHolder.Write returns true.

// send payload to tag
TagHolder.Write("my-topic", "hello world!");

// print success message to console
Console.WriteLine("Payload sent successfully!");

Overall, the TagHolder provides a convenient way to read and write Coreflux tags using C# code. By using the TagHolder in your Digital Worker Asset code, you can easily interact with the Coreflux data hub and integrate Coreflux tags into your application logic.

Shortly, we will add up the events to this TagHolder. 😎

Using the Digital Worker in a DataHub! It is like magic in the form of code!🧙‍♂️

Troubleshooting

When working with the Digital Worker Asset, users may encounter various issues that can prevent the asset from functioning correctly. Here are some common issues that users may face and some tips on how to troubleshoot them:

  • Compilation errors: If you encounter any compilation errors when building your project, the errors will be provided to the Error Console topic. Make sure to check the topic for any error messages and resolve them before running your code.
GODAMN!! Not another comma error “;” 😡
  • Program errors: Even if your code compiles successfully, you may still encounter errors at runtime, such as conversion errors or other exceptions. These errors will also appear in the Error Console topic. If you encounter any errors, you can use try-catch blocks to catch them and handle them gracefully. This will ensure that your program continues running even if errors occur.
  • Program not running: Due to the compilation of the asset we have a 15-script limitation per digital worker. Since we use the compiler and machine sometimes each digital worker will consume about 500Mb of memory, this is one of the reasons for our limitation since we want to handle performance as well.

By following these tips, you can minimize the risk of encountering issues when working with the Digital Worker Asset. If you still encounter any issues, you can refer to the Error Console topic to check.

For more information and help join our Discord community “Coreflux — Flux the System”.

--

--