Node.js: devided stdout using SPAWN with exe program - c++

I wrote some C++ program which is waiting for 103 data strings and response on the output with 9 strings. I would like to send data from the node app and receive the data from the output. Unfortunately I found that the output data, that I display in the console, it is not from the same reading cycle.
So the question is: Does stdin and stdout in node app has any buffer which I can flush or something?
Here is my c++ program:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
cout << "Program is running";
vector <string> tab(103);
string nazwa;
int index = 0;
do {
for (int i = 0; i < 103; i++) {
getline(cin, nazwa);
if (!nazwa.empty() && nazwa[nazwa.size() - 1] == '\n')
nazwa.erase(nazwa.size() - 1);
if (!nazwa.empty() && nazwa[nazwa.size() - 1] == '\r')
nazwa.erase(nazwa.size() - 1);
tab[i] = nazwa;
}
for (int i = 0; i < 9; i++) {
cout << index << ": " << i+1 << endl;
}
index++;
} while (true);
return 0;
}
It simply wait for 103 strings with data from node and give back 9 stings.
Here is my node program:
var prg = null;
var str = "";
var counter = 0;
var spawn = require('child_process').spawn;
var fun = function(){
console.log("fun() start");
prg = spawn('test.exe');
};
fun();
setInterval(function() {
//console.log(".");
prg.stdin.write('0.5\n');
}, 10);
prg.stdout.on('data', function(data) {
str = data.toString(), lines = str.split(/(\r&\n)/g);
for (var i=0;i<lines.length; i++) {
console.log('node counter: '+counter+", passed data: "+lines[i]);
}
counter++;
});
The output in the node console proving that the output is divided:
fun() start
node counter: 0, passed data: Program is running
node counter: 1, passed data: 0: 1
0: 2
0: 3
0: 4
0: 5
0: 6
0: 7
node counter: 2, passed data: 0: 8
0: 9
node counter: 3, passed data: 1: 1
1: 2
1: 3
1: 4
1: 5
1: 6
1: 7
1: 8
1: 9
UPDATE:
I found 3 solutions. I had to pass data via IPC (Inter Process Communication) to avoid these standard in/out buffers.
Possible ways:
Nodejs Addons
Named pipe
Sockets communication
I used great git project JSON for Modern C++ to pass easy in use data container.
I created JSON structure and put it into the file. Now I can read this file and send it to the pipe. The main problem with pipes is that its hard to control databytes from the pipe. But if you use JSON for Modern C++ addon, you will know when you have all data.
Because in every pipe reading I wont know how many bytes I will send this time, so I created bigger buffer and after reading all data from pipe I just cut them and use JSON parser again.
After reading data (c++ side) Im preparing this data to send it back to node.
Node code:
var prg = null;
var fs = require('fs');
//parse JSON from file
var obj = JSON.parse(fs.readFileSync('data.json', 'utf8'));
var net = require('net');
var path = require('path');
var counter = 0;
//create pipe
var server = net.createServer(function(req) {
setInterval(function() {
var strobj = JSON.stringify(obj);
req.write(strobj); // send data to pipe every second
}, 1000);
rehttps://stackoverflow.com/questionsq.on('data', function(c) {
var size = c.length;
console.log(counter+': bytesize of JSON: ' + size);
var reciv = JSON.parse(c);
counter++;
console.log("Display JSON:\n %j ",reciv);
});
});
server.listen('\\\\.\\pipe\\JointsPipe');
// Spawning EXE program
var spawn = require('child_process').spawn;
var prg = spawn('test.exe');
prg.on('close', function(){
console.log("Pipe Closed");
});
C++ Program
I hope it will help someone.

I assume that node.js child_process.spawn creates a child process, which is sharing it's parents stdin, stdout and stderr streams. Since both the parent and the child are writing to those streams you'll get an 'intermixed' output. You can try to redirect each of those to different files and get not divided output. Or you could try to use some shared resource to communicate between the parent and the child process (eg. some socket or named pipe)

Related

C++ call functions internally

I'm working with following code which gives access to low level monitor configuration using Windows APIs
https://github.com/scottaxcell/winddcutil/blob/main/winddcutil/winddcutil.cpp
And I would like to create a new function that increases or decreases the brightness, I was able to do this using Powershell but since the C++ code looks somewhat easy to understand I want to have a crack at it and try my luck and hopefully integrate it with an ambient light sensor later.
The powershell code I have is as follows which works with above executable: (its very crude at this stage)
$cb = [int]([uint32]("0x" + ((C:\Users\Nick\WindowsScripts\winddcutil-main\x64\Release\winddcutil.exe getvcp 0 10) -join "`n").split(" ")[2]))
if ($args[0] -eq "increase") {
if ( $cb -ne 100) {
$nb = "{0:x}" -f ($cb + 10)
C:\Users\Nick\WindowsScripts\winddcutil-main\x64\Release\winddcutil.exe setvcp 0 10 $nb
}
} elseif ($args[0] -eq "decrease") {
if ( $cb -ne 10) {
$nb = "{0:x}" -f ($cb - 10)
C:\Users\Nick\WindowsScripts\winddcutil-main\x64\Release\winddcutil.exe setvcp 0 10 $nb
}
}
It gets current brightness and if argument given is "increase" and if brightness is not already 100 then adds 10, in case of "decrease" it subtracts 10. Values are coveted to and from hex to decimals.
I understand if I want to integrate this inside the C++ code directly I would have something like following:
int increaseBrightness(std::vector<std::string> args) {
size_t did = INT_MAX;
did = std::stoi(args[0]);
//0 is monitor ID and 10 is the feature code for brightness
//currentBrightness = getVcp("0 10")
//calculate new value
//setVcp("0 10 NewValue")
}
Ultimetaly I would like to call the executable like "winddcutil.exe increasebrightness 0" (0 being the display ID)
I can keep digging around on how to do the calculation in C++ but internally calling the functions and passing the arguments so far turned out to be very challenging for me and I would appreciate some help there.
you need to add a needed option here
line 164
std::unordered_map<std::string,std::function<int(std::vector<std::string>)>> commands
{
{ "help", printUsage },
{ "detect", detect},
{ "capabilities", capabilities },
{ "getvcp", getVcp },
{ "setvcp", setVcp},
{"increasebrightness ", increaseBrightness } // update here
};
to get current brightness you can't use getVcp api due to its result will be printed to stdout , it isn't returned via returned value, follow getVcp to get brighness value , use this
DWORD currentValue;
bool success = GetVCPFeatureAndVCPFeatureReply(physicalMonitorHandle, vcpCode, NULL, &currentValue, NULL);
if (!success) {
std::cerr << "Failed to get the vcp code value" << std::endl;
return success;
}
then
define your increaseBrightness like
int increaseBrightness(std::vector<std::string> args) {
size_t did = INT_MAX;
did = std::stoi(args[0]);
DWORD currentBrightness;
bool success = GetVCPFeatureAndVCPFeatureReply(
physicalMonitorHandle, vcpCode, NULL, &currentBrightness, NULL);
if (!success) {
std::cerr << "Failed to get the vcp code value" << std::endl;
return success;
}
//example + 10
auto newValue = did + 10;
success = setVcp({"0", "10", std::to_string(newValue)});
if(success)
{
// your handler
}
// 0 is monitor ID and 10 is the feature code for brightness
// currentBrightness = getVcp("0 10")
// calculate new value
// setVcp("0 10 NewValue")
}
test for passing argument:
https://godbolt.org/z/5n5Gq3d7e
note: make sure your have increaseBrightness's declaration before std::unordered_map<std::string,std::function<int(std::vector<std::string>)>> commands to avoid compiler's complaint

Sending messages and roadside to roadside (R2R) communication in Veins

I'm new in Omnet Veins. I try to create my own application. So first of all, I have done this in the existing TraciDemo11p files (I have just kept the files name and modify the code).
In the first step, I want to make all nodes sending a HelloMsg (a new packet that I have created .msg .h and .cc).
To well understand how messages are exchanged between nodes, I launched the simulation and all is well, but I cannot realize if the messages are received by nodes or not.
This is a screenshot of what I have:
enter image description here
I followed the transmission of the message between the application, mac and phy layers. I can see that the message is successfully transmitted by node1 for example. But does the message on node[0] "packet was not detected by the card. power was under sensitivity threshold" mean that the packet was not received by node[0]?. If it is the case, how can I fix that? Also, I cannot find the source file of this message (apparently, in PhyLayer80211p.cc or BasehyLayer.cc but I cannot find it).
In the second step, I want to use two RSUs. Nodes broadcast a helloMessage and then each RSU will repeat the received signal. To clarify more, this exactly what I have:
First of all. I add another RSU to the veins example as follows:
##########################################################
# RSU SETTINGS #
# #
# #
##########################################################
*.rsu[0].mobility.x = 6490
*.rsu[0].mobility.y = 1000
*.rsu[0].mobility.z = 3
*.rsu[1].mobility.x = 7491
*.rsu[1].mobility.y = 1000
*.rsu[1].mobility.z = 3
*.rsu[*].applType = "TraCIDemoRSU11p"
*.rsu[*].appl.headerLength = 80 bit
*.rsu[*].appl.sendBeacons = false
*.rsu[*].appl.dataOnSch = false
*.rsu[*].appl.beaconInterval = 1s
*.rsu[*].appl.beaconUserPriority = 7
*.rsu[*].appl.dataUserPriority = 5
Also, I made two maxInterferenceDistance, one of the nodes and the other for the RSUs:
##########################################################
# 11p specific parameters #
# #
# NIC-Settings #
##########################################################
*.connectionManager.sendDirect = true
*.connectionManager.maxInterfDist = 1000m #2600m
*.connectionManager.drawMaxIntfDist = false #false
*.connectionManager.maxInterfDistNodes = 300m
*.connectionManager.drawMaxIntfDistNodes = false
*.**.nic.mac1609_4.useServiceChannel = false
*.**.nic.mac1609_4.txPower = 20mW
*.**.nic.mac1609_4.bitrate = 6Mbps
*.**.nic.phy80211p.sensitivity = -89dBm
*.**.nic.phy80211p.useThermalNoise = true
*.**.nic.phy80211p.thermalNoise = -110dBm
*.**.nic.phy80211p.decider = xmldoc("config.xml")
*.**.nic.phy80211p.analogueModels = xmldoc("config.xml")
*.**.nic.phy80211p.usePropagationDelay = true
*.**.nic.phy80211p.antenna = xmldoc("antenna.xml", "/root/Antenna[#id='monopole']")
To make the transmission range of RSU different on that of nodes, I made this change in the isInRange function of the baseConnectionMannager:
bool BaseConnectionManager::isInRange(BaseConnectionManager::NicEntries::mapped_type pFromNic, BaseConnectionManager::NicEntries::mapped_type pToNic)
{
double dDistance = 0.0;
if ((pFromNic->hostId == 7) || (pFromNic->hostId == 8)) {
EV<<"RSU In range from: "<<pFromNic->getName()<<" "<<pFromNic->hostId<<" to: "<<pToNic->getName()<<" "<<pToNic->hostId<<"\n";
if(useTorus) {
dDistance = sqrTorusDist(pFromNic->pos, pToNic->pos, *playgroundSize);
} else {
dDistance = pFromNic->pos.sqrdist(pToNic->pos);
}
return (dDistance <= maxDistSquared);
} else {
if(useTorus) {
dDistance = sqrTorusDist(pFromNic->pos, pToNic->pos, *playgroundSize);
} else {
dDistance = pFromNic->pos.sqrdist(pToNic->pos);
}
return (dDistance <= maxDistSquaredNodes);
}
}
Where node IDs 7 and 8 are the RSUs in the scenario I run.
In addition, I have the TraciDemo11p (for nodes) and TraciDemoRSU11p (for RSUs) modified as follow:
- In the TraciDemo11p, nodes when enter the network broadcast a Hello message to all their neighbors. The code is:
void TraCIDemo11p::initialize(int stage) {
BaseWaveApplLayer::initialize(stage);
if (stage == 0) {
HelloMsg *msg = createMsg();
SendHello(msg);
}
}
HelloMsg* TraCIDemo11p::createMsg() {
int source_id = myId;
double t0 = 0;
int port = 0;
char msgName[20];
sprintf(msgName, "send Hello from %d at %f from gate %d",source_id, t0, port);
HelloMsg* msg = new HelloMsg(msgName);
populateWSM(msg);
return msg;
}
void TraCIDemo11p::SendHello(HelloMsg* msg) {
findHost()->getDisplayString().updateWith("r=16,green");
msg->setSource_id(myId);
cMessage* mm = dynamic_cast<cMessage*>(msg);
scheduleAt(simTime() + 10 + uniform(0.01, 0.02), mm);
}
void TraCIDemo11p::handleSelfMsg(cMessage* msg) {
if (dynamic_cast<HelloMsg*>(msg)) {
HelloMsg* recv = dynamic_cast<HelloMsg*>(msg);
ASSERT(recv);
int sender = recv->getSource_id();
if (sender == myId) {
EV <<myId <<" broadcasting Hello Message \n";
recv->setT0(SIMTIME_DBL(simTime()));
sendDown(recv->dup());
}
}
else {
BaseWaveApplLayer::handleSelfMsg(msg);
}
}
void TraCIDemo11p::onHelloMsg(HelloMsg* hmsg) {
if ((hmsg->getSource_id() == 7) || (hmsg->getSource_id() == 8)) {
EV <<"Node: "<<myId<<" receiving HelloMsg from rsu: "<<hmsg->getSource_id()<<"\n";
} else {
EV <<"Node: "<<myId<<" receiving HelloMsg "<<hmsg->getKind()<<" from node: "<<hmsg->getSource_id()<<"\n";
NBneighbors++;
neighbors.push_back(hmsg->getSource_id());
EV <<"Node: "<<myId<<" neighbors list: ";
list<int>::iterator it = neighbors.begin();
while (it != neighbors.end()) {
EV <<*it<<" ";
it++;
}
}
}
void TraCIDemo11p::handlePositionUpdate(cObject* obj) {
BaseWaveApplLayer::handlePositionUpdate(obj);
}
On the other hand, RSUs just repeat the message they received from nodes. So, I have on the TraciDemoRSU11p:
void TraCIDemoRSU11p::onHelloMsg(HelloMsg* hmsg) {
if ((hmsg->getSource_id() != 7) && (hmsg->getSource_id() != 8))
{
EV <<"RSU: "<<myId<<" receiving HelloMsg "<<hmsg->getKind()<<" from node: "<<hmsg->getSource_id()<<" at: "<<SIMTIME_DBL(simTime())<<" \n";
//HelloMsg *msg = createMsg();
//SendHello(msg);
hmsg->setSenderAddress(myId);
hmsg->setSource_id(myId);
sendDelayedDown(hmsg->dup(), 2 + uniform(0.01,0.2));
}
else {
EV<<"Successful connection between RSUs \n";
EV <<"RSU: "<<myId<<" receiving HelloMsg "<<hmsg->getKind()<<" from node: "<<hmsg->getSource_id()<<"\n";
}
}
After the execution of this code, I can see:
a few numbers of vehicles receiving the hello message from their neighbors.
also, just a few messages were received by the two RSUs.
Each RSUs repeats the signal it receives, but there is no communication between the two RSU, which are supposed in the transmission of one another.
And always I have a lot of this message "packet was not detected by the card. power was under sensitivity threshold" printed on my screen.
Is there any problem in the transmission range or it is a question of interference? Also, I would like to mention that in the analysis there is no packet loss.
Thanks in advance.
Please help.

error c# serial port display weighting scale continuously to richtextbox

I'm trying to read the data weighing scale to my computer using c# serial port.
in putty output like this :
60KG
60KG
60KG
60KG
then i display it in richtextbox using the script below:
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired) //<-- Makes sure the function is invoked to work properly in the UI-Thread
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); })); //<-- Function invokes itself
else
{
while (_serialPort.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
String tampung = _serialPort.ReadExisting();
String tampungy = Regex.Replace(tampung, #"[^\d]", "").Trim();
richTextBox2.AppendText(tampungy + System.Environment.NewLine);
richTextBox2.ScrollToCaret();
}
}
}
but displays like this
6
0
6
0
6
0
Is there something wrong ?
It seems like you are reading the data as each character arrives. To demonstrate this, you could do this:
var data = new byte[_serialPort.BytesToRead];
_serialPort.Read(data, 0, data.Length);
tampungy = string.Join(" ", data.Select(b => b.ToString("X2"));
richTextBox2.AppendText(tampungy + System.Environment.NewLine);
richTextBox2.ScrollToCaret();
It should print out the hex encoding of each byte read. 0D 0A (CR LF) and 0A (LF) are linebreaks. 30 or 39 are digits (0-9).
You should buffer the input until a newline is read.
private StringBuilder _buffer = new StringBuilder();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired) //<-- Makes sure the function is invoked to work properly in the UI-Thread
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); })); //<-- Function invokes itself
else
{
while (_serialPort.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
_buffer.Append(_serialPort.ReadExisting());
}
// Look for the first linebreak in the buffer
int index = Enumerable.Range(0, _buffer.Length).FirstOrDefault(i => _buffer[i] == '\n'); // 0 if not found
while (index > 0) {
// Extract and remove the first line
string tampung = _buffer.ToString(0, index);
_buffer.Remove(0, index + 1);
String tampungy = Regex.Replace(tampung, #"\D+", "");
richTextBox2.AppendText(tampungy + System.Environment.NewLine);
richTextBox2.ScrollToCaret();
// Look for the next linebreak, if any
index = Enumerable.Range(0, _buffer.Length).FirstOrDefault(i => _buffer[i] == '\n'); // 0 if not found
}
}
}

go - How to use golang goroutine, select and if statement to return?

I'm trying to make a "if" statement in goroutine.
Question: how to make 10 from 10?
var jr = make(chan int, 10)
var clients = 10 // The number of clients varies with time.
func rpcMethod(num int) {
time.Sleep(time.Duration(rand.Intn(int(time.Second))))
jr <- num
}
func postHandler(num int) {
// wait RPC data
for {
select {
case msg := <-jr:
{
if msg == num {
fmt.Println(num, "hello from", msg)
return
}
}
}
}
}
func main() {
for i := 0; i < clients; i++ {
go postHandler(i)
go rpcMethod(i)
}
fmt.Scanln()
}
Result 2/10
5 hello from 5
2 hello from 2
Ok, there are multiple problems.
First and foremost, it does not work because when something is read from a channel, it disappears (it is not a broadcast, only one thread can read the message).
So in order for your code to pseudo-work, you could do this:
if msg == num {
fmt.Println(num, "hello from", msg)
return
}else {
// not my number, put it back in the channel
jr <- num
}
You will ge the expected result, but there is still a problem: your program won't shutdown properly. I guess this is only for experiment/learning purposes, but in a real program you would use a completely different code. Tell me if another version would interest you.
After postHandler receives msg from channel jr, that value is not in the channel anymore for another postHandler to find. Channels do not broadcast.
Either send the value back into the channel if it's not equal to num or restructure your code entirely.

Storing list of times and sorting as ascending

I am using C# .Net 4
I have a list of times in seconds, up to 600 (10 min), In the format of ##.###, Currently I am gathering these into a List string and then using .Sort()
Here is an example of what I am getting when I write it to a txt file
193.225 193.225 88
195.489 195.489 89
197.741 197.741 90
199.993 199.993 91
2.334 2.334 2
20.213 20.213 13
202.246 202.246 92
204.51 204.51 93
206.762 206.762 94
I need help finding an easy way to put these in the correct order, I do nothing I can use List int because of the tab that seperates each field.
Here is my current code
private void ExportMarkCollections(MarkCollection collection, string exportType)
{
if (exportType == "vixen3")
{
foreach (MarkCollection mc in MarkCollections)
{
MessageBox.Show(String.Format("{0}", mc.Name));
mymarks = "";
foreach (TimeSpan time in mc.Marks)
{
mymarks = mymarks + time;
}
MessageBox.Show(String.Format("{0}", mymarks));
}
}
if (exportType == "audacity")
{
List<string> BeatMarks = new List<string>();
iMarkCollection = 0;
foreach (MarkCollection mc in MarkCollections)
{
iMarkCollection++;
foreach (TimeSpan time in mc.Marks)
{
BeatMarks.Add(time.TotalSeconds + "\t" + time.TotalSeconds + "\t" + iMarkCollection);
if (MarkCollections.Count == 1)
iMarkCollection++;
}
}
BeatMarks.Sort();
string filter = "Audacity Marks (*.txt)|*.txt|All Files (*.*)|*.*";
saveFileDialog.DefaultExt = ".txt";
saveFileDialog.Filter = filter;
DialogResult result = saveFileDialog.ShowDialog();
if (result == DialogResult.OK)
{
string name = saveFileDialog.FileName;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(name))
{
foreach (string bm in BeatMarks)
{
file.WriteLine(bm);
}
}
}
}
}
Mike's comment is correct. You can, for example, do this (note - no error handling in this code!):
public static int CompareStrings(string a, string b)
{
double x = double.Parse(a.Substring(0, a.IndexOf('\t')));
double y = double.Parse(b.Substring(0, a.IndexOf('\t')));
return x.CompareTo(y);
}
and then:
list.Sort(CompareStrings);
However, I would suggest not throwing the numbers into a tab delimited string in the first place. Data should be kept in as "clean" format as possible until the last moment (for example, until display in the UI), otherwise you're just making things harder on yourself (you have to worry about regional settings, decimal dot vs comma, etc). Consider these potential problems if the file you're outputting will be read on a different machine / by a different application.