How does my C application communicate with bluetoothctl? - stdout

In C language, I want to develop an application to run bluetoothctl, and then send command to it and receive the info, like we run bluetoothctl in console.
int main(void)
{
int fd, err = 0;
char* tty;
wait_pid = -1;
printf("BLEapp program start.......\r\n");
if (wait_pid == -1) {
printf("Start to run bluetoothctl......\r\n");
if ((pid = fork()) < 0) {
err = 1;
printf("Create new progress failed.\r\n");
}
else if (pid == 0) {
// Child progress, run as default when xid = 0x0 and mastAddr = 0x0
execl("/root/bluez-5.42/client/bluetoothctl", "bluetoothctl", NULL);
}
}
else {
printf("The child procress is still running.....\r\n");
err = 1;
}
//tty = ttyname(STDIN_FILENO);
//printf("stdin name is %s.\r\n", tty);
//fd = open(tty, O_WRONLY);
//if (fd < 0) {
// printf("Open stdin error..............\r\n");
//}
while (1) {
sleep(2);
fputs("devices\n", stdin);
//write(fd, "devices\n", 8);
}
return err;
}
I run bluetoothctl as child process, and want to send "devices\n" command to it, and read the listed devices. But it doesn't work.
Please help me to fix this problem.
Thanks.

Related

electron.clipboard.readText() returns empty string

I try to use require('electron').clipboard.readText() and just get an empty string, although I have some text in the clipboard.
I see this in Console.app (not sure if this is related):
Failed to set up CFPasteboardRef 'Apple CFPasteboard general'. Error: <error: 0x7fffa6d6fda0> { count = 1, transaction: 0, voucher = 0x0, contents =
"XPCErrorDescription" => <string: 0x7fffa6d70048> { length = 18, contents = "Connection invalid" }
}
How can I fix this?
I think this is because the Electron app was started via execve() in a forked process (fork() +daemon()` actually).
One workaround is to execute /usr/bin/open as a wrapper, like so (pseudo code):
open -a argv[0] --args args[1...]
Or basically this code:
char** args = parse_args(cmd);
char* arg0 = find_in_path(args[0]);
pid_t pid = fork();
if (pid == 0) {
daemon(1, 0);
#ifdef __APPLE__
{
// We cannot directly use `execv` for a GUI app on MacOSX
// in a forked process
// (e.g. issues like https://stackoverflow.com/questions/53958926/).
// But using `open` will work around this.
int argc = 0;
for(; args[argc]; ++argc);
char** args_ext = malloc(sizeof(char*) * (argc + 5));
arg0 = "/usr/bin/open";
args_ext[0] = arg0;
args_ext[1] = "-a";
args_ext[2] = args[0];
args_ext[3] = "--args";
for(int i = 0; ; ++i) {
args_ext[i + 4] = args[i + 1];
if(!args[i + 1])
break;
}
args = args_ext;
}
#endif
execv(arg0, args);
exit(-1);
} else if (pid > 0) { // master
// go on ...
free(args);
} else {
// error handling...
}
(Basically via this commit.)

wxWidgets serial Commuication

I have absolutely no experience in programming serial communication and since I'm stuck with my code I'd really appreciate your help! Thank you already!
So now to my problem:
I got a generator on which are several different sensors who communicate over CAN with a microcontroller. This mc itself communicates with a device from USBTin again over CAN. On the USBTin, a little board, is mainly a CAN controller and a microcontroller which are precoded from its developer.
So my task now is to open my COM Port, send the right messages to the USBTin (those are "S5" for the baudrate and 'O' for Open CAN) and then receive the data.
First of all the functions and my problem:
The problem is that in my output textfield stands something like "PPPPPPPPPP,Râö". There are always these 10 P's and some random characters. I have no idea where the P's or these additional "Râö" comes from. The actual output string shoud be something like "T1E18001F8". I tested that with hTerm, which is a terminal programm for serial communication.
OPEN:
long Serial::Open()
{
if (IsOpened()) return 0;
#ifdef UNICODE
wstring wtext(port.begin(),port.end());
#else
string wtext = port;
#endif
hComm = CreateFile(wtext.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE) {return 1;}
if (PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |
PURGE_RXCLEAR) == 0) {return 2;}//purge
//get initial state
DCB dcbOri;
bool fSuccess;
fSuccess = GetCommState(hComm, &dcbOri);
if (!fSuccess) {return 3;}
DCB dcb1 = dcbOri;
dcb1.BaudRate = baud;
if (parity == 'E') dcb1.Parity = EVENPARITY;
else if (parity == 'O') dcb1.Parity = ODDPARITY;
else if (parity == 'M') dcb1.Parity = MARKPARITY;
else if (parity == 'S') dcb1.Parity = SPACEPARITY;
else if (parity == 'N') dcb1.Parity = NOPARITY;
dcb1.ByteSize = (BYTE)dsize;
if(stopbits==2) dcb1.StopBits = TWOSTOPBITS;
else if (stopbits == 1.5) dcb1.StopBits = ONE5STOPBITS;
else if (stopbits == 1) dcb1.StopBits = ONE5STOPBITS;
dcb1.fOutxCtsFlow = false;
dcb1.fOutxDsrFlow = false;
dcb1.fOutX = false;
dcb1.fDtrControl = DTR_CONTROL_DISABLE;
dcb1.fRtsControl = RTS_CONTROL_DISABLE;
fSuccess = SetCommState(hComm, &dcb1);
delay(60);
if (!fSuccess) {return 4;}
fSuccess = GetCommState(hComm, &dcb1);
if (!fSuccess) {return 5;}
osReader = { 0 };// Create the overlapped event. Must be closed before
exiting to avoid a handle leak.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL) {return 6;}// Error creating overlapped event;
abort.
fWaitingOnRead = FALSE;
osWrite = { 0 };
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL) {return 7;}
if (!GetCommTimeouts(hComm, &timeouts_ori)) { return 8; } // Error getting
time-outs.
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutMultiplier = 15;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 15;
timeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hComm, &timeouts)) { return 9;} // Error setting time-
outs.
return 0;
}
WRITE:
bool Serial::Write(char *data)
{
if (!IsOpened()) {
return false;
}
BOOL fRes;
DWORD dwWritten;
long n = strlen(data);
if (n < 0) n = 0;
else if(n > 1024) n = 1024;
// Issue write.
if (!WriteFile(hComm, data, n, &dwWritten, &osWrite)) {
if (GetLastError() != ERROR_IO_PENDING) {fRes = FALSE;}// WriteFile
failed, but it isn't delayed. Report error and abort.
else {// Write is pending.
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE))
fRes = FALSE;
else fRes = TRUE;// Write operation completed successfully.
}
}
else fRes = TRUE;// WriteFile completed immediately.
return fRes;
}
READCHAR:
char Serial::ReadChar(bool& success)
{
success = false;
if (!IsOpened()) {return 0;}
DWORD dwRead;
DWORD length=1;
BYTE* data = (BYTE*)(&rxchar);
//the creation of the overlapped read operation
if (!fWaitingOnRead) {
// Issue read operation.
if (!ReadFile(hComm, data, length, &dwRead, &osReader)) {
if (GetLastError() != ERROR_IO_PENDING) { /*Error*/}
else { fWaitingOnRead = TRUE; /*Waiting*/}
}
else {if(dwRead==length) success = true;}//success
}
//detection of the completion of an overlapped read operation
DWORD dwRes;
if (fWaitingOnRead) {
dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);
switch (dwRes)
{
// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
{/*Error*/ }
else {
if (dwRead == length) success = true;
fWaitingOnRead = FALSE;// Reset flag so that another
opertion
can be issued.
}// Read completed successfully.
break;
case WAIT_TIMEOUT:
// Operation isn't complete yet.
break;
default:
// Error in the WaitForSingleObject;
break;
}
}
return rxchar;
}
And Finally the excerpt of the main in wxWidgets to display the received data:
void GUI_1_2Frame::OnConnectButtonClick(wxCommandEvent& (event))
{
char tempString[10] = {0};
bool ReadChar_success = true;
char temp_Char;
/* Preset Serial Port setting */
Serial com(com_x, 115200, 8, NOPARITY, 1);
char* buffer;
if(connection_flag)
{
/* Port was connected, Disconnect Button unsed*/
com.Close();
wxMessageBox(_("Port closed"),_("Info!"),wxICON_INFORMATION);
connection_flag = 0;
ConnectButton->SetLabel("Connect");
TextCtrl1->SetValue("");
}
else
{
/* If open() == true -> INVALID HANDLE */
if(com.Open())
{
wxMessageBox(_("Port not available"),_("ERROR!"),wxICON_ERROR);
}
else /* Port Opened */
{
TextCtrl1->SetValue(com.GetPort());
ConnectButton->SetLabel("Disconnect");
connection_flag = 1;
}
if(com.Write("S5"))
{
TextCtrl1->SetValue("Baudrate sent!\n");
delay(100);
if(com.WriteChar('O'))
{
TextCtrl1->SetValue("Baudrate & Open Command sent!");
int i =0;
while(i<10)
{
temp_Char = com.ReadChar(ReadChar_success);
tempString[i] = temp_Char;
i++;
}
com.WriteChar('C');
com.Close();
//com.readSerialPort(data, MAX_DATA_LENGTH);
TextCtrl2->SetValue(tempString);
//wxMessageOutput::Get()->Printf("%s", tempString);
}
else
{
TextCtrl1->SetValue("Open Command Error!"); }
}
else
{
TextCtrl1->SetValue("Error!");
}
}
}
Since I am not native speaking englisch I say sorry for my language mistakes.
Thank everybody a lot and again I really appreciate every single hint!
Greetings,
MSol

Pthread semaphore TCP

I wanna create 2 threads in client, each thread will send a message to server and get rebounce or download a file from server, using TCP protocole. This program run very well when I didn't add pthread in it. After I created 2 threads in client, It doesn't communicate with server. Normally, thread will tell server which operation it wants, then server respond, but when one thread send the message, there is no respond from server, and this thread exit immediately, next thread occupy the semaphore but exit without chose the operation.
Code
void semaphore()
{
int nThread = 2;
int nSemaphore = 1;
int nRet = -1;
pthread_t threadIDs[nThread];
nRet = sem_init(&sem, 0, nSemaphore);
if(nRet == -1)
{
perror("Semaphore intialization failed!!!\n");
exit(EXIT_FAILURE);
}
int i;
for (i = 0; i < nThread; ++i)
{
nRet = pthread_create(&threadIDs[i], NULL, thread, NULL);
if(nRet != 0)
{
perror("pthreas_create failed!!!\n");
exit(EXIT_FAILURE);
}
}
for(i = 0; i < nThread; ++i)
{
nRet = pthread_join(threadIDs[i], NULL);
if(nRet != 0)
{
printf("Threan %d join failed!!!\n", i);
exit(EXIT_FAILURE);
}
}
sem_destroy(&sem);
}
enter code here
void *thread(void* p)
{
pthread_t id = pthread_self();
sem_wait(&sem);
pthread_mutex_lock(&mutex);
int operation ;
//向服务器(特定的IP和端口)发起请求
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
serv_addr.sin_family = AF_INET; //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
serv_addr.sin_port = htons(1234); //端口
printf("\nThis is client %ld", id);
printf("\nWhich operation do you want:\n");
printf("1:Sending message to server and get rebound\n");
printf("2:Downlown a file from server\n");
scanf("Your chose:%d", &operation);
switch(operation)
{
case 1:
{
sendMessage(serv_addr);
break;
}
case 2:
{
download(serv_addr);
break;
}
default:
break;
}
sem_post(&sem);
pthread_mutex_unlock(&mutex);
}
From terminal
This is client 139671599236864
Which operation do you want:
1:Sending message to server and get rebound
2:Downlown a file from server
Your choise:1
This is client 139671590844160
Which operation do you want:
1:Sending message to server and get rebound
2:Downlown a file from server
Can someone tell me where is the problem?

How get trap with indy TidSNMP component

I'm using c++builderXE with Indy 10.5.7 and I'm trying to receive trap from another agent snmp.
I have no info describing how to do the program to receive trap.
Below you can find the snippet of code which I'm trying to use now.
The ReceiveTrap() method always return 0, which means non data received.
I tested the PC configuration with another program I made several years ago using spare API and the trap is received so I don't this it should be a configuration problem.
Have you some suggestions of hat I'm wrong in the routine below?
void __fastcall TForm1::LabelReceiveTrapClick(TObject * Sender)
{
static bool status = false;
int ists;
String Fun = "[SimpleReceiveTrap] ";
TSNMPInfo * infoSnmp = 0;
try
{
status = !status;
if (status)
{
std::auto_ptr< TIdSNMP >clientSnmp(new TIdSNMP(NULL));
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 1000;
clientSnmp->Binding->Port = 162;
while (status)
{
Application->ProcessMessages();
ists = clientSnmp->ReceiveTrap();
Mylog(L"%s ReceiveTrap status = [%d]", Fun.c_str(), ists);
if (ists > 0)
{
infoSnmp = clientSnmp->Trap;
}
}
}
}
catch (Exception & ex)
{
Mylog(L"%s ERROR", Fun.c_str(), ex.Message.c_str());
}
}
That is not the correct way to set the listening Port for receiving traps. Reading the Binding property allocates and binds a socket to a local IP/Port using the TIdSNMP::BoundIP and TIdSNMP::BoundPort properties. You can't change that socket's local Port after it has already been bound, so your assignment of the Binding->Port property is effectively a no-op.
For that matter, you are trying to manipulate the wrong socket anyway. The Binding socket is used for sending queries to the remote SNMP system. TIdSNMP uses a separate socket for receiving traps. TIdSNMP has a separate TrapPort property for specifying the listening Port of that socket. When the Binding is accessed, the trap socket is allocated and bound to Binding->IP and TIdSNMP::TrapPort. The TrapPort property defaults to 162.
std::auto_ptr< TIdSNMP >clientSnmp(new TIdSNMP(NULL));
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 1000;
clientSnmp->TrapPort = 162; // <--
...
ists = clientSnmp->ReceiveTrap();
Looking at Indy's changelog, there have been some trap-related changes to the listening socket since 10.5.7 was released, so you may need to upgrade to a newer Indy version to get bug fixes. Or you could download the latest version and then just add IdSNMP.pas to your project directly, at least.
Using only the Indi component I can't read the trap rev 2c
But I found a solution using TWSocket and TSNMPInfo which seems to works well
Belowe the code I used:
To get the data I use a TWSocket fro FPiette components suite:
void __fastcall TForm1::LabelStartServerTracSnmpClick(TObject * Sender)
{
String Fun = "[LabelStartServerTracSnmp] ";
try
{
if (WSocket1->State == wsClosed)
{
WSocket1->Proto = "udp";
WSocket1->Addr = "0.0.0.0";
WSocket1->Port = 162;
WSocket1->Listen();
}
else
{
WSocket1->Close();
}
}
catch (Exception & ex)
{
Mylog(L"%s ERROR: [%s]", Fun.c_str(), ex.Message.c_str());
}
}
To analyze the data received I use the Indy
void __fastcall TForm1::WSocket1DataAvailable(TObject * Sender, WORD ErrCode)
{
char buffer[1024];
int len, cnt, srcLen;
TSockAddrIn srcSocket;
String rcvmsg, remHost, s1, s2, Fun = "[WSocket1DataAvailable] ";
TIdSNMP * clientSnmp = NULL;
TSNMPInfo * infoSnmp = NULL;
try
{
srcLen = sizeof(srcSocket);
len = WSocket1->ReceiveFrom(buffer, sizeof(buffer), srcSocket, srcLen);
if (len >= 0)
{
buffer[len] = 0;
rcvmsg = String(buffer, len);
__try
{
clientSnmp = new TIdSNMP(NULL);
infoSnmp = new TSNMPInfo(clientSnmp);
infoSnmp->DecodeBuf(rcvmsg);
cnt = infoSnmp->ValueCount;
if (cnt > 0)
{
// ---------------------------------------------------
for (int idx = 0; idx < cnt; ++idx)
{
s1 = infoSnmp->ValueOID[idx];
s2 = infoSnmp->Value[idx];
Mylog(L"[%s] Trap : [%s] => [%s]", s1.c_str(), s2.c_str());
}
}
}
__finally
{
if (infoSnmp)
{
delete infoSnmp;
infoSnmp = 0;
}
if (clientSnmp)
{
delete clientSnmp;
clientSnmp = 0;
}
}
}
}
catch (Exception & ex)
{
Mylog(L"%s ERROR", Fun.c_str(), ex.Message.c_str());
}
}

Problem with wsarecv while using with IOCP

I am new to IOCP and struggling with this for last few weeks.
I have pasted some core part of my code below related to IOCP.This may not be executed perfectly as I clipped some part to make it easy to understand.
I am struggling while receiving the data.As it comes to wsarecv in worket thread, wsarecv returns WSA_IO_PENDING error code so I call WSAGetOverlappedResult to check operation to be completed.
Twist comes here, rather it proceed and call my local function ProcessTelegramData after WSAGetOverlappedResult , same part of code(wsarecv called again) is executed again by another worker thread which try to call ProcessTelegramData and buffer value is invalid in it.
I am unable to understand
why another thread calling wsarecv again when WSAGetOverlappedResult is called and
why buffer value is getting invalidated?
unsigned LicTCPServer::WorkerThread(LPVOID lpParam)
{
//int nThreadNo = (int)lpParam;
LicTCPServer* pThis = reinterpret_cast<LicTCPServer*>(lpParam);
void *lpContext = NULL;
OVERLAPPED *pOverlapped = NULL;
CClientContext *pClientContext = NULL;
DWORD dwBytesTransfered = 0;
int nBytesRecv = 0;
int nBytesSent = 0;
DWORD dwBytes = 0, dwFlags = 0;
//Worker thread will be around to process requests, until a Shutdown event is not Signaled.
while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&lpContext,
&pOverlapped,
INFINITE);
if (NULL == lpContext)
{
//We are shutting down
break;
}
//Get the client context
pClientContext = (CClientContext *)lpContext;
if ((FALSE == bReturn) /*|| ((TRUE == bReturn) && (0 == dwBytesTransfered))*/)
{
//Client connection gone, remove it.
pThis->RemoveFromClientListAndFreeMemory(pClientContext);
continue;
}
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();
//printf("reached %d\n",pClientContext->GetOpCode());
printf("Get Queued received\n");
switch (pClientContext->GetOpCode())
{
case OP_READ:
{
//Once the data is successfully received, we will print it.
//pClientContext->SetOpCode(OP_WRITE);
pClientContext->ResetWSABUF();
dwFlags = 0;
//int a = recv(pClientContext->GetSocket(), p_wbuf->buf, p_wbuf->len, 0);
//Get the data.
if(WSARecv(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("Error occured at WSARecv()\n");
return 0;
}
}
DWORD byteTr = 0;
WSAGetOverlappedResult(pClientContext->GetSocket(),p_ol,&byteTr,TRUE,&dwFlags);
if( byteTr > 0 )
{
//doing some operatin on data received
printf("Process tele called\n");
g_pLicServFunc->ProcessTelegramData(pClientContext->GetSocket(), p_wbuf->buf, byteTr);
}
if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
}
break;
case OP_WRITE:
char szBuffer[MAX_BUFFER_LEN];
//Send the message back to the client.
pClientContext->SetOpCode(OP_READ);
pClientContext->SetTotalBytes(dwBytesTransfered);
pClientContext->SetSentBytes(0);
//p_wbuf->len = dwBytesTransfered;
dwFlags = 0;
DWORD temp;
//Overlapped send
printf("reached Going to send\n");
//send(pClientContext->GetSocket(), p_wbuf->buf,p_wbuf->len, 0);
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
&temp, dwFlags, p_ol, NULL);
if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
break;
default:
printf("reached to default\n");
//We should never be reaching here, under normal circumstances.
break;
} // switch
} // while
return 0;
}
I had a similar issue with WSARecv where it always queued to the io completion queue, even if it succeeded immediately. I had to ignore a return value indicating success and instead handle the queued result that I got from GetQueuedCompletionStatus.

Resources