I have been using mono and the excellent Twitterizer libraries to post tweets from my Raspberry Pi. The goal being to tweet pictures captured by a webcam periodically.
The problem I have is that when I make a call to "UpdateWithMedia" on mono it just hangs - seemingly forever. Works fine on Windows.
I've created the following unit tests to demonstrate. Both pass on Windows. On Mono/linux "SimpleTwitterPost" passes but "ImagePost" hangs just after writing the filename to the console.
[Test]
public void SimpleTwitterPost()
{
var response = TwitterStatus.Update(tokens, "Here's an automated tweet from my new Raspberry Pi Brain");
Console.WriteLine(response.ErrorMessage);
Assert.That(response.Result, Is.EqualTo(RequestResult.Success));
}
[Test]
public void ImagePost()
{
string filename = "Pics" + Path.DirectorySeparatorChar + "DukeInABush.jpg";
Assert.That(File.Exists(filename));
Console.WriteLine("File to open: {0}", filename);
var response = TwitterStatus.UpdateWithMedia(tokens, "Me in a bush", filename);
Console.WriteLine("Did it!");
Assert.That(response.Result, Is.EqualTo(RequestResult.Success));
}
I have tried the overload of "UpdateWithMedia" which takes a byte array but no luck. I can read the file into the byte array fine but the call to "UpdateWithMedia" hangs as before.
For ref, using mono/.NET 4.0 on Archlinux on raspberry pi (arm).
Anyone got any experience with Twitterizer on this platform?
Related
I am trying to read data and convert it from a Modbus RTU sensor using .NET 7. Everything is working on my Linux-x64 machine but not when i try to run it on the RevPi core S linux-arm...
Modbus RTU config
Sensor Instructions
I am using FluentModbus version 5.0.2:
fluentClient = new ModbusRtuClient()
{
BaudRate = 9600,
Parity = Parity.None,
StopBits = StopBits.One
};
fluentClient.Connect("/dev/ttyUSB" + port, ModbusEndianness.LittleEndian);
Console.WriteLine("Reading Calibration");
var calibration = fluentClient.ReadHoldingRegisters(1, 8704, 4);
var hexCalibration = Convert.ToHexString(calibration);
foreach (var item in calibration)
{
Console.Write(item);
}
foreach (var item in hexCalibration)
{
Console.Write(item);
}
//The code below works perfect on my machine running Ubuntu 22.04(linux-x64) but does not work //on RevPi Core running Debian custom Buster image (Linux-arm).
var floatCalibration = fluentClient.ReadHoldingRegisters<float>(1, 8704, 4);
Console.WriteLine("calibration K: " + floatCalibration[0]);
Console.WriteLine("calibration B: " + floatCalibration[1]);
Terminal output My computer:
Reading Calibration
000631541535764
0000003F9A993940
calibration K: 0.5
calibration B: 2.9
Terminal output RevPi Core:
Reading Calibration
000631541535764
0000003F9A993940
Unhandled exception. System.DataMisalignedException: A datatype misalignment was detected in a load or store instruction.
at exsys.Program.Main(String[] args) in /home/user/FunctionTest/Program.cs:line 179
Aborted
And this is line 179: Console.WriteLine("calibration K: " + floatCalibration[0]);
Is it not possible to use .Net7 Span<float> on linux Arm? I have tried different setups, but no luck yet. Maybe someone else have run in to this issue?
Tried dotnet publish to self contained linux-x64 and everything works fine. i only get the error when compiling to linux-arm and running it.
Tried different converting setups but no luck.
I have updated the image on the RevPi Core S released in November 2022, but it did not help.
Tried first running on .NET 6 and now on .NET 7. Same error on both.
FluentModbus is breaking alignment here:
https://github.com/Apollo3zehn/FluentModbus/blob/master/src/FluentModbus/Client/ModbusClient.cs#L155
and then calls MemoryMarshal.Cast which is a problem on ARM, because the documentation says
This method is supported only on platforms that support misaligned memory access or when the memory block is aligned by other means.
ARM is not a platform that supports misaligned memory access.
A good workaround would be to allocate a float[], call the version of ReadHoldingRegisters that returns Span<byte>, and call CopyTo(MemoryMarshal.AsBytes(destFloatArray)).
I have an asp.net core API that was recently updated from .net5 to .net6.
There is a piece of code that should read a duration of an audio file. The code that seems to have worked on previous versions was this:
try
{
//
// NAudio -- Windows only
//
using var fileReader = new AudioFileReader(filePath);
return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (DllNotFoundException)
{
try
{
//
// LibVLCSharp is crossplatform
//
using var libVLC = new LibVLC();
using var media = new Media(libVLC, filePath, FromType.FromPath);
MediaParsedStatus parsed = Task.Run(async () => await media.Parse(MediaParseOptions.ParseNetwork, timeout: 2000).ConfigureAwait(false)).Result;
if (parsed != MediaParsedStatus.Done) throw new ArgumentException("Could not read audio file");
if (!media.Tracks.Any(t => t.TrackType == TrackType.Audio) || (media.Duration <= 100)) throw new ArgumentException("Could not read audio from file");
return Convert.ToInt32(Math.Ceiling(TimeSpan.FromMilliseconds(media.Duration).TotalSeconds));
}
catch (Exception ex) when (ex is DllNotFoundException || ex is LibVLCSharp.Shared.VLCException)
{
try
{
using var fileReader = new Mp3FileReader(filePath);
return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (InvalidOperationException)
{
throw new ArgumentException("Could not read audio file");
}
}
}
The application was deployed on Linux and, I don't know which part of the code did the exact calculation (I am assuming the VLC part), but since the update to .NET6, all of these fail, and since the last fallback is NAudio, we get the following exception:
Unable to load shared library 'Msacm32.dll' or one of its dependencies.
I am using Windows, but I tried running the app with WSL, and I can't get the VLC part to run either - it always throws the following exception (even after installing vlc and vlc dev SDK):
LibVLC could not be created. Make sure that you have done the following:
Installed latest LibVLC from nuget for your target platform.
Unable to load shared library 'libX11' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibX11: cannot open shared object file: No such file or directory at LibVLCSharp.Shared.Core.Native.XInitThreads()
at LibVLCSharp.Shared.Core.InitializeDesktop(String libvlcDirectoryPath)
at LibVLCSharp.Shared.Helpers.MarshalUtils.CreateWithOptions(String[] options, Func`3 create)
Is there any clean way to read a duration of an audio file on all platforms?
Needless to say, NAudio works like a charm on Windows, and so does the VLC (with the proper nuget package).
If you install ffmpeg, you can do this quite easily. ffmpeg comes installed in most linux distros by default, but in case it isn't, you can install it with your favorite package manager.
sudo apt install ffmpeg
To install it in windows, you'll need to download the build files, extract it, and add it to the PATH.
Next, install Xabe.FFMpeg package in your project.
Finally, you can call the static method Xabe.FFMpeg.FFMpeg.GetMediaInfo() to get all information regarding your audio file. Here is a sample snippet that I tested on my linux machine.
using System;
using System.IO;
using Xabe.FFmpeg;
namespace Program;
public static class Program
{
public static void Main(string[] args)
{
string filename;
if (args.Length == 0)
{
Console.WriteLine("No arguments found! Provide the audio file path as argument!");
return;
}
else if (File.Exists(filename = args[0]) == false)
{
Console.WriteLine("Given file does not exist!");
return;
}
try
{
var info = FFmpeg.GetMediaInfo(filename).Result;
TimeSpan duration = info.Duration;
Console.WriteLine($"Audio file duration is {duration}");
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
The error you are seeing is because we were assuming that you would display a video on linux, using X11, so we are always initializing X11. See here.
We shouldn't do that for your use case(because you may not have a GUI available). Please report the issue here : https://code.videolan.org/videolan/LibVLCSharp/-/issues
or even better, submit a pull request on github or gitlab.
As for your question of why did it work on .net 5 and not anymore, I'm not sure we have enough info to tell why, because you didn't send us the error message from that machine.
I would encourage you to take a look at atldotnet. It is a small, well maintained completely managed code / cross platform library without any external dependencies and was accurate detecting audio file duration in all of my test cases (more accurate than ffmpeg). Most common audio formats are supported.
var t = new Track(audioFilePath);
// Works the same way on any supported format (MP3, FLAC, WMA, SPC...)
System.Console.WriteLine("Duration (ms) : " + t.DurationMs);
I have a Python backend running machine learning algorithms. I want to use the same backend for both an Excel plugin (C#) and a website. I want both interfaces to send my training data (thousands of lines of numbers in arrays) to the same Python application and retrieve the results in the form of another array up to a few thousand lines.
The website would fetch data from a SQL database and send that data to Python, while the Excel plugin would take the data that is in the current worksheet and send that data to Python. I need to be able to create numpy arrays in Python before continuing to process the data. Note that the website would be running on the same machine where the Python application resides. I still haven't decided what I will use to code the website, but I was leaning towards Node.js.
I have done some research and found a few options:
1- Named pipes
2- Sockets
3- RPC server such as gRPC or XML-RPC.
4- Writing the data to a file and reading it back in Python
5- Web Service
Note: I would need the Python "server" to be stateful and keep the session running between calls. So I would need to have a kind of daemon running, waiting for calls.
Which one would you experts recommend and why? I need flexibility to handle several parameters and also large arrays of numbers. Using IronPython is not an option because I am running Keras on Python, which apparently does not support IronPython.
I had the same problem recently.
I used a named pipe to transport data from python to my c# server, hope it helps you.
Python:
import win32pipe, win32file
class PipeServer():
def __init__(self, pipeName):
self.pipe = win32pipe.CreateNamedPipe(
r'\\.\pipe\\'+pipeName,
win32pipe.PIPE_ACCESS_OUTBOUND,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
1, 65536, 65536,
0,
None)
#Carefull, this blocks until a connection is established
def connect(self):
win32pipe.ConnectNamedPipe(self.pipe, None)
#Message without tailing '\n'
def write(self, message):
win32file.WriteFile(self.pipe, message.encode()+b'\n')
def close(self):
win32file.CloseHandle(self.pipe)
t = PipeServer("CSServer")
t.connect()
t.write("Hello from Python :)")
t.write("Closing now...")
t.close()
For this code to work you need to install pywin32 (best choice is from binarys): https://github.com/mhammond/pywin32
C#-Server:
using System;
using System.IO;
using System.IO.Pipes;
class PipeClient
{
static void Main(string[] args)
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "CSServer", PipeDirection.In))
{
// Connect to the pipe or wait until the pipe is available.
Console.Write("Attempting to connect to pipe...");
pipeClient.Connect();
Console.WriteLine("Connected to pipe.");
Console.WriteLine("There are currently {0} pipe server instances open.",
pipeClient.NumberOfServerInstances);
using (StreamReader sr = new StreamReader(pipeClient))
{
// Display the read text to the console
string temp;
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("Received from server: {0}", temp);
}
}
}
Console.Write("Press Enter to continue...");
Console.ReadLine();
}
}
You can use Python for .NET (Python.NET). It may require some changes to your code, but then it should work very well, once everything is in good shape.
Python.NET allows two-way communication between CPython and CLR.
Let me give you a neat and quick recipe, in the form of example code.
There are basically two ways to tie python in the backend of C# (or a C# winform app or gui or something similar).
Method1: Iron Python. In this method you install a .net package in your visual studio called IronPython. I would not prefer this, because assuming your machine learning model uses keras or a lot of other libraries. It would be another quest to get you installations ready and working in IronPython. And most importantly, it is not as good as your common virtual env or conda environment.
Method2: (The Good Method): Create a Custom Process in your C# that takes arguments from your GUI, knows the path to your script and your python env. Using all these things, it calls your python code exactly the way you would call it in your terminal and pass arguments to it.
Now the tasty example code (I have used this simple trick and it always helps make my black screen python stuff look good with the cover of C# apps).
Python Part
import sys
a = sys.argv[1]
b = sys.argv[2]
print("The Sum = ", float(a)+float(b))
The C# Part
So here is the python process/function that you need to call on the click event of your sum button in the application
static void PythonProcess()
{
//1) Create Process Info
var psi = new ProcessStartInfo();
//Conda Env Path
psi.FileName = #"C:\Users\jd\.conda\pkgs\py\python.exe";
//2) Provide Script and the Arguments
var script = #"C:\Users\jd\Desktop\script.py";
var a = "15";
var b = "18";
psi.Arguments = $"\"{script}\" \"{a}\" \"{b}\"";
//3) Process Configuration
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
//4) Execute Process and get Output.
var errors = "";
var results = "";
using(var process = Process.Start(psi))
{
errors = process.StandardError.ReadToEnd();
results = process.StandardOutput.ReadToEnd();
}
//5) Display Output
Console.WriteLine("ERRORS: ");
Console.WriteLine(errors);
Console.WriteLine();
Console.WriteLine("RESULTS: ");
Console.WriteLine(results);
}
Calling Python from C# is easily possible via Pyrolite where your Python code is running as a Pyro4 server. It should be fast enough to handle "large arrays of numbers" however you didn't specify any performance constraints.
I had the same issue and seem to end up with named pipes. Here is a nice example of how to set it up to talk C# => Python, assuming C# is the server.
It can use the same way to talk back or just Python.net to call directly through CLR as shown here. I use the latter.
I am brand new to Universal Windows Apps (Win 10). I am trying to port a console application over to UWP that acts as a remote testing and administrative console for a custom Windows Service application. I can not seem to find any solid example code to demonstrate where to place a socket listener in the MainPage.xaml.cs file (or wherever it's supposed to go). I have been successful with porting the MSDN example into a method that serializes a PCL model object with Json and sends it to the server. I just can not seem to handle the listener correctly. I don't think that I am using it in the right place, especially when it comes to the async usage. I am having protocol\port usage errors because it's basically saying that it is already open (I just tossed it in the test method). I would like to deserialize the Json response that is received and use it to populate a List. Here is an example of what is working for me for sending.
private async void Pulse(string target)
{
if (target == null || target == string.Empty)
{
greetingOutput.Text = "No Ip specified";
return;
}
else
{
try
{
Windows.Networking.Sockets.StreamSocket socket = new Windows.Networking.Sockets.StreamSocket();
Windows.Networking.HostName serverHost = new Windows.Networking.HostName(target);
await socket.ConnectAsync(serverHost, serverPort);
Stream streamOut = socket.OutputStream.AsStreamForWrite();
StreamWriter writer = new StreamWriter(streamOut);
HeartBeatPing heartBeatPing = new HeartBeatPing(GetLocalIp(), target);
string msg = JsonConvert.SerializeObject(heartBeatPing);
await writer.WriteLineAsync(msg);
await writer.FlushAsync();
Stream streamIn = socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(streamIn);
string response = await reader.ReadLineAsync();
}
catch (Exception xCeption)
{
greetingOutput.Text += "\n" + xCeption.ToString();
}
}
}
Some of you might notice from the greetingsOutput.text that I have started with the "C# Hello World" example from Microsoft's training site.
I would also like to add that I am not going to be using any HTTP for this because there is going to be some custom encryption and other "things" happening with the Json objects that will require separate ports.
I'm not far enough into my Universal Windows Apps with XAML and C# (Unleashed) books to have even a clue as to what I am doing. I am however well seasoned C# programmer in other platforms such as MVC, Windows Service, Console, and others. I have a solid understand of enterprise class patterns and practices based on my knowledge of "The Gang of Four".
Any help would be greatly appreciated. Thank you.
(https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DatagramSocket)
Here is a sample. There are CPP, js, and cs code in this sample, I've only tested the cs code. Wish this can help you.
I have a problem with executing python script over ssh (using c# and SharpSSH).
I have connection and can write simple commands like "startx" and "sudo shutdown ..."
When I try to run a python script freezes the program and nothing happens. I have tried exactly the same procedure with "putty" and it work as expected.
The python script runs and i get data (print 'No Laser, fast movement: Dx=', stepx, ' Dy=', stepy) whitch is importen for my application.
C# SharpSSH connection
ssh = new SshStream(host, user, password);
//Set the end of response matcher character
ssh.Prompt = "#";
//Remove terminal emulation characters
ssh.RemoveTerminalEmulationCharacters = true;
//Reading from the SSH channel
string response = ssh.ReadResponse();
return response;
C# start Gcode_executer.py does not work and freezes program(on pc) raspberry pi dont run python file
try
{
ssh.Write("sudo python cnc/Gcode_executer.py"); // Write ssh to RPI
// works it in putty
if (ssh.CanRead == true)
{
return ssh.ReadResponse(); // return string from terminal from RPI
}
else
{
return "No response";
}
}
catch
{
return "Catch NO response";
}
What I can do to solve the problem?
Try writing a shell script (on the pi) that runs the .py file and calling that shell script.
It works now.
My python script have sub files. therefore must be cd Into the folder until it has the correct path to sub files