Calculating a moving average in C# with IronPython Data Stream - c#

I have a sensor that is displaying real-time data through a Python script, running on IronPython. Unfortunately, IronPython does not support pandas, so I am unable to use the pd.rolling_mean function in my Python script, or perform much data processing in real-time (as far as I understand).
When I run the below program in Visual Studio, a console application appears, and the data from the sensor starts streaming in. My goal is to calculate the rolling_mean of this data stream, and then to trigger an event once that rolling_mean exceeds a certain value.
I am limited to IronPython, because that is what the sensor company requires in order to run their real-time data script. Unfortunately, I am having trouble finding ways to process that data stream in real-time.
I was wondering if there is a way for me to write the rolling_mean in C# on the data stream that is coming in - similar to the following question: Calculate a moving std in C#.
Thank you for any feedback and support! My current code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IronPython.Hosting;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter Y to begin:");
var input = Console.ReadLine();
var py = Python.CreateEngine();
var engine = Python.CreateEngine();
var paths = engine.GetSearchPaths();
paths.Add("C:\\Python34\\Lib\\site-packages");
engine.SetSearchPaths(paths);
try
{
py.ExecuteFile("C:\\Users\\MyName\\Desktop\\Sensor_Data.py");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
Console.WriteLine("Press Enter to Exit");
Console.ReadLine();
}
}
}

Related

How to get symbols from TwinCAT in windows 10?

I have to use Beckhoff I/O in real-time mode (not PLC project), because the final goal is to make a Soft-PLC, where the program runs on the cumputer and not on Beckhoff. So in Visual Studio I wrote a c# code which opens an existing TwinCAT project in background (with a task and some variables linked), activates the configuration and then gets the symbols from that task, so I can use them to control in realtime the variables (e.g. reading an input or writing an output). The problem is I can't get the symbols! (Im using the SymbolLoaderFactory.Create method). I created a class "Controlling" in the same namespace which contains some methods like GoConfig(), Open(), Activate() etc..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
using System.IO;
using TCatSysManagerLib;
using System.Management;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Collections;
using System.Xml;
using TwinCAT.Ads;
using TwinCAT.Ads.ValueAccess;
using TwinCAT.Ads.TypeSystem;
using TwinCAT.TypeSystem;
namespace TCControl
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string solName = "solution1";
string solPath = $#"B:\...solutionPath...\{solName}";
string[] terminal = new string[1];
terminal[0] = "EK1100";
string ipAddress = "10.157.4.69.1.1";
int port = 301;
Controlling co = new Controlling();
MessageFilter.Register();
//go to configuration mode
co.GoConfig(ipAddress);
//open the solution
string[,] treeItemsandTypes = co.Open(solPath, solName, ipAddress, terminal);
co.Activate(solPath, solName);
//obtain symbols
ISymbolLoader symbolLoader = co.SymbolsGetter(ipAddress, port);
ISymbol[] symbols = new ISymbol[symbolLoader.Symbols.Count];
int i = 0;
foreach (ISymbol symbol in symbolLoader.Symbols)
{
symbols[i] = symbol;
i++;
}
Console.WriteLine("\n" + symbols[0].ToString());
Console.WriteLine("\n" + symbols[1].ToString());
All projects I created to test this had 2 variables linked to the task.
Everything works fine until the SymbolsGetter method. From the Controlling class:
public ISymbolLoader SymbolsGetter(string indirizzo, int port)
{
using (TcAdsClient client = new TcAdsClient())
{
System.Threading.Thread.Sleep(2000);
client.Connect(indirizzo, port);
//Creates the Symbol Objects as hierarchical tree
SymbolLoaderSettings settings = new SymbolLoaderSettings(SymbolsLoadMode.Flat, ValueAccessMode.IndexGroupOffsetPreferred);
ISymbolLoader symbolLoader = SymbolLoaderFactory.Create(client, settings);
//System.Threading.Thread.Sleep(2000);
return symbolLoader;
}
}
The Thread.Sleep is because otherwise the client.Connect generated an error.
It only works in debug if I add a break point on "return symbolLoader" and if I pass over it with the mouse puntator to see the value (of symbolLoader).
I tried to insert another sleep but nothing, it doesn't work. Im actually starting thinking it is black magic.
Another problem is that I can't get symbols from all projects (nether using the debug technique of before). And even when it works I can't use the name of the symbol to write a high/low signal to that variable. So nothing is working, I'm just able to create and open a project, a task etc.
Just one more information: im using windows 10 (maybe TwinCAT works better on windows 7 or xp, but I have to make it work on windows 10).
I have to do everything without touching or seeing the TwinCAT project window, it has to stay in background. I'm not a programmer and I'm quite new into the Beckhoff/TwinCAT world. Please if anyone can help me I'd be incredibly thankful to him.
If you want to use the ADS library from beckhoff you cannot not have a Beckhoff PLC-Runtime in the background.
With the ADS-lib you access the symbols in the PLC Runtime which has an Ethercat Master with which it can communicate with the Beckhoff Ethercat IOs.
If you do not want to use a Beckhoff Plc-Runtime (and it's not really clear to me why you wouldn't want to) you need another kind of Ethercat Master in order to communicate with the IOs.
I have to use Beckhoff I/O in real-time mode (not PLC project), because the final goal is to make a Soft-PLC, where the program runs on the cumputer and not on Beckhoff.
This is confusing, because the Beckhoff runtime runs on computer besides windows.
If you want to control IOs without real time capability you can buy an Advantech PCI IO card for example and use their c# sdk.
You can't use c# to access Beckhoff IOs without a Beckhoff runtime in the background.
Twincat doesn't work better on windows 7 or xp in fact Twincat 3 is not even supported on windows xp and new machines only use windows 10 for security and support reasons.

Powershell addscript and invoke from C# not displaying result on command line

I've the below powershell script file
C:\user\deskptop\script1.ps1
The contents of the script is just the below:
get-process
i'm trying to create a C# console app to get the output of this script on console. When i execute the script outside C# it runs fine but when i execute it inside C# it doesn't produce anything. i'm trying use addscript and invoke.
C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management.Automation;
using System.Collections.ObjectModel;
namespace InvokePowerShellScriptFrmCsharp1
{
class Program
{
static void Main(string[] args)
{
string script = #"C:\\Users\\Desktop\\script1.ps1";
PowerShell shell = PowerShell.Create();
shell.AddScript(script);
//shell.AddCommand("get-process");
shell.Invoke();
//shell.AddScript(script).Invoke();
Collection<PSObject> pSObjects = shell.Invoke();
foreach (PSObject p in pSObjects)
{
Console.WriteLine(p.ToString());
}
Console.WriteLine("Press any key to continue");
Console.ReadLine();
}
}
}
When i execute the above i get the console with 'Press any key to continue' but no output before that.
but if i just try the below i get the result
shell.addcommand("get-process");
I want to get this working with addscript coz in the future if there is more than one command in the powershell script then i need to be able to execute the script from C# for desired results.
i've tried many links to try research but don't seem to be getting it to work.
https://blogs.msdn.microsoft.com/kebab/2014/04/28/executing-powershell-scripts-from-c/
https://www.reddit.com/r/csharp/comments/692mb1/running_powershell_scripts_in_c/
Could someone please let me know where i could be going wrong.
Try loading the script contents first, then passing that to the AddScript method:
string script = File.ReadAllText(#"C:\Scripts\script1.ps1");

need guidance for speech recognition engine with custom keywords c#

I have an windows form app. I need to add speech recognition into it in order to shorten the processing time for product entry. we need this speech recognition in Turkish. if it was in english, because of wrong pronunciation it would give a lot of false results. So we need in Turkish. But windows offline speech recognition engine doesnt support Turkish.
Actually We need max 100 keywords in order to succeed this. we don't need whole language in process. So if I can create a language by adding a word and train the engine for that with a kind of training as speech training in windows, it would be great.
So I need guidance to start or move forward for this task. I have looked at the cmusphnfix but it doesnt have turkish language also. But I dont know if I can create a custom language for 100 words with correct pronunciation. if so how can ı do it in c#.
note: we dont want to use google and microsoft online services. we are looking other options.
Thanks in advance.
Windows desktop versions have built in APIs for speech recognition. These include grammar support for identifying the words or meaning of what was spoken. I don't know if Turkish is supported.
Perhaps https://stackoverflow.com/a/5473407/90236 or https://learn.microsoft.com/en-us/previous-versions/office/developer/speech-technologies/hh361633(v%3doffice.14) can help you get started
https://www.sestek.com has good Turkish speech recognition. As for 100 keywords, on that scale it is easier to recognize whole speech and just look for keywords in transcription. That will give you better accuracy because speech recognition uses more context. When you just look for keywords you do not have context so the recognition is actually less accurate.
this is script for C# console app
if you want this in windows forms, just copy static void recognize and all in this and paste it in class Form : Form1, or where you want. write recognize(); in button1_click, or where you want. in windows forms do not copy anything else!
write this:
using System;
using System.Runtime.CompilerServices;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
using System.Linq.Expressions;
namespace speechrecognition
{
class Program
{
static string a { get; set; }
static void Main(string[] args)
{
recognize();
}
static void recognize()
{
SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine();
Choices colorChoice = new Choices(new string[] { "gugl", "noutpad" });
GrammarBuilder colorElement = new GrammarBuilder(colorChoice);
Choices bothChoices = new Choices(new GrammarBuilder[] { colorElement });
Grammar grammar = new Grammar((GrammarBuilder)bothChoices);
recognizer.LoadGrammar(grammar);
try
{
recognizer.SetInputToDefaultAudioDevice();
RecognitionResult result = recognizer.Recognize();
try
{
if (result.Text != null)
{
switch (result.Text.ToString())
{
// Here you add keywords like other two
// and write the into choices color choice too
case "noutpad":
Process.Start(#"notepad.exe");
Console.WriteLine("Notepad opened!");
recognize();
break;
case "gugl":
Process.Start(#"chrome.exe");
Console.WriteLine("Google opened!");
recognize();
break;
}
}
else
{
Console.WriteLine("I dont hear you!");
recognize();
}
}
catch (System.NullReferenceException)
{
recognize();
}
}
catch (InvalidOperationException exception)
{
Console.WriteLine("I dont hear you!");
Console.ReadLine();
recognize();
}
finally
{
recognizer.UnloadAllGrammars();
recognize();
}
}
}
}

Invoking PS script from C# code (Visual studio 2017)

I am trying to invoke my PS script from C# code.
**PS code. -- Try.ps1**
Write-Host "HelloHost"
Write-Debug "HelloDebug"
Write-Output "HelloOutput"
echo "tofile" > $PSScriptRoot/a.txt
**C# code**
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;
namespace TryitOut
{
class Program
{
static void Main(string[] args)
{
using (PowerShell pshell = PowerShell.Create())
{
string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
pshell.AddScript(path + "\\Try.ps1");
IAsyncResult result = pshell.BeginInvoke();
while (result.IsCompleted == false)
{
Console.WriteLine("Waiting for PS script to finish...");
Thread.Sleep(1000);
}
Console.WriteLine("Finished!");
Console.ReadKey();
}
}
}
}
When I run "Try.ps1" independently it runs ok and creates a.txt ans shows console output as expected.
But, it not getting invoked/executed via this C# code.
Question 1. can you please help, what I am doing wrong?
Q 2. How can I see PS console output when invoking Try.ps1 via C# code
Thank you for your time :).
Dealing with output from the PowerShell object is done in two ways. One is the direct return values of the Invoke call, and the other is via various streams. In both cases, you are responsible for dealing with the data; the console does not automatically output them as when you run a script in the standard PowerShell window. For example, to get the results from Write-Object, you can add the following to your C# code after your while loop:
foreach(PSObject pso in pshell.EndInvoke(result))
{
Console.WriteLine(pso);
}
This works fine for the simple strings in your example, but for complex objects with multiple properties, you need to pull the individual properties by name. For example:
string propValue = pso.Members["PropertyName"].Value.ToString();
Have a look at a previous answer of mine to see one way to convert complex objects to your own type: Dealing with CimObjects with PowerShell Inside C#
Handle the debug, information, verbose, etc like this:
foreach(DebugRecord dbr in pshell.Streams.Debug)
{
Console.WriteLine(dbr);
}
You will need to add this to the start of your script as well:
$DebugPreference = 'continue'

wmic via .NET or C#

All,
Please forgive my ignorance of C#/.NET, I am absolutely new to both (mostly Java, C/C++) and find myself tasked with creating some code that performs the same thing as the "wmic qfe" and "wmic os" commands available at the DOS prompt.
Can this be done? If so, any help is appreciated. I am trying to working my way through the System.Management.Instrumentation namespace since wmic is an acronym for Windows Management Instrumentation Command (according to Google), but have as yet to discover anything useful.
Thanks in advance,
Toddw
Instead of using the Management class, you can simply invoke the wmic.exe which is a WMI console as you can figure out from the exe name itself. Here is the code that I used to open notepad on a remote computer using WMIC invoked through C#.net. Try it out.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace RemoteProcessDemo
{
class Program
{
static void Main(string[] args)
{
string strComputerName = "";
string strProcString = "";
try
{
strComputerName = args[0];
Process.Start("wmic", "/node:" + strComputerName + " process call create notepad.exe");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Regards,
Tushar
You will indeed need to use the System.Management namespace to perform WMI queries. There is lots info on using WMI from C#, Microsoft's is (archived) here
For your specific cases:
qfe - query the Win32_QuickFixEngineering class
os - query the Win32_OperatingSystem class

Categories