Here is my code:
#include "MyClass.h"
#include <qstring.h>
#include <qdebug.h>
MyClass::MyClass()
{
QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
int counter=0;
while(counter<ports.size())
{
QString portName = ports[counter].portName;
QString productId= ports[counter].productID;
QString physicalName = ports[counter].physName;
QString vendorId = ports[counter].vendorID;
QString friendName = ports[counter].friendName;
string convertedPortName = portName.toLocal8Bit().constData();
string convertedProductId = productId.toLocal8Bit().constData();
string convertedPhysicalName = physicalName.toLocal8Bit().constData();
string convertedVendorId = vendorId.toLocal8Bit().constData();
string convertedFriendName = friendName.toLocal8Bit().constData();
cout << "Port Name: " << convertedPortName << endl;
cout << "Product ID:" << convertedProductId << endl;
cout << "Physical Name: " << convertedPhysicalName << endl;
cout << "Vendor Id: " << convertedVendorId << endl;
cout << "Friend Name: " << convertedFriendName << endl;
cout << endl;
counter++;
}
}
I have connected "Dreamcheeky Thunder Missile Launcher" USB toy, but I am unable to get it's Vendor ID or product ID or atleast anything related to it! See the following image
But using USBDView software, I can get all the details. See the following image
What is matter with My code? Or if it is simply not suitable?
Just running the installer for the toy and checking what it comes up with, it doesn't describe any API or documentation for accessing it as a serial port.
If you used some sort of monitoring program on their program you could maybe reverse engineer how it commands the device.
It may be easier just to interface with their UI directly. Using a program like AHK or calling SendInput() to coordinates relative to the upper left corner of their UI, you could command the directions of the device.
EDIT: More links related to this:
Because the USB device doesn't get listed as a COM# (how serial port shows up), and it is a HID device, you need a library that can talk to that. Here are some links that should help you get there:
http://www.qtcentre.org/threads/41075-USB-HID-connect-on-QT
http://www.signal11.us/oss/hidapi/
https://github.com/iia/Qt_libusb
It also looks like the guys at Robo Realm have done it already:
http://www.roborealm.com/help/DC_Missile.php
http://www.roborealm.com/help/USB_HID.php
http://www.roborealm.com/tutorial/usb_missile_launcher/slide010.php
Hope that helps.
Related
I am developing a network scanner in C++ with the help of libtins library, I can be able to get MAC addresses and IP but I want to go further to know the vendor(eg: Intel Corporate) and Device Name (eg: DESKTOP-TO5P0BD) in C++
codes to get Mac and IP
// Retrieve the ARP layer info
const ARP& arp = pdu.rfind_pdu<ARP>();
std::cout << "Found :" << arp.sender_ip_addr() << ", " << arp.sender_hw_addr() << std::endl;
// Checking if it is an ARP reply?
if (arp.opcode() == ARP::REPLY) {
// Let's check if there's already an entry for this address
auto iter = addresses.find(arp.sender_ip_addr());
if (iter == addresses.end()) {
std::cout << "saving " << arp.sender_ip_addr() << ", " << arp.sender_hw_addr() << std::endl;
// We haven't seen this address. Save it.
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr() });
IPv4Address ip = arp.sender_ip_addr();
NetworkInterface iface(ip);
//std::cout << iface.name() << std::endl;
}
else {
std::cout << "already seen " << arp.sender_ip_addr() << ", " << arp.sender_hw_addr() << std::endl;
// We've seen this address. If it's not the same HW address, inform it
if (arp.sender_hw_addr() != iter->second) {
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
<< iter->second << " but also at " << arp.sender_hw_addr()
<< std::endl;
}
}
}
In order to get the vendor from the MAC address, you can have a look at this MAC OUI vendor database mantained by Wireshark. It's a text file with a simple format.
In order to get the "device name", you can do a NetBIOS name lookup. This StackOverflow question may help you.
If you'd like the Vendor Name from the MAC, you could get the MAC by reading arp -a (probably via the winapi). Next you need to search a vendor db, the wireshark list is good, there's also this one. As for the "Device Name", you could check this with WMI. Other than the more complex winapi for this, you could use a library like this one, which is much simpler. You'd need to make a request to the Win32_ComputerSystem class, which contains the Device Name and model number, among other things. MAC addresses can also be retrieved by WMI, instead make the query to Win32_NetworkAdapter - it gives all of the interfaces so be sure to find the right one!
I have trouble when using my USRP b200 mini. Indeed, I wasn’t able to use it in transmitter mode. I work with two b100 and one b200.
Until now, if I use one USRP b100 in transmitter mode and another one in receiver mode, everything works. If I use one USRP b100 in transmitter mode and my USRP b200 in receiver mode everything still works. But if I do the opposite, I am not able to detect my transmitted signal anymore.
Can someone could help me please ?
I use these C++ code lines to parameter my USRP:
void Radio_Tx_Rx::initialize(int TX){
printf("%s",KYEL);
if (TX){
cout << "TRANSMITTER INITIALISATION " << endl;
string usrp_addr("type=b200");
usrp = uhd::usrp::multi_usrp::make(usrp_addr);
usrp->set_tx_rate(fe);
usrp->set_tx_freq(fc);
usrp->set_tx_gain(20); //I tested gain from 0 to 80 with a step of 10
usrp->set_tx_antenna("TX/RX");
uhd::stream_args_t
stream_args("fc32");
tx_stream = usrp->get_tx_stream(stream_args);
cout << " " << string(50, '-') << endl;
usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
} else {
cout << " RECEIVER INITIALISATION "<< endl;
string usrp_addr("type=b100");
usrp = uhd::usrp::multi_usrp::make(usrp_addr);
usrp->set_rx_rate(fe);
usrp->set_rx_freq(fc);
usrp->set_rx_antenna("TX/RX");
uhd::stream_args_t
stream_args("fc32");
rx_stream = usrp->get_rx_stream(stream_args);
cout << " " << string(50, '-') << endl;
usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
printf("%s", KNRM);
}
In efforts to learn more C++, I have chosen - you know - something fun to do and that is writing to random application's memory. The code I have written seems to work on all applications but I am having difficulties getting it to work with Google Chrome tabs.
What I am trying to do is simply change my score on Slope (on y8.com) for which I have the memory address with the help of cheat engine. The problem seems to be retrieving the Process ID of the tab. Using Chrome's Task Manager, I translated the tab's address to hex, opened the process in cheat engine and found the score address.
Here the problem comes. Whenever I use GetWindowThreadProcessId(window, &processID); cout << processID, it doesn't print the ID which can be seen in chrome's task manager for the game's tab. In fact, it prints the ID of chrome as a whole (which I know because in chrome's task manager, "chrome" has that ID). And the score cannot be written to or read from chrome's processID. If I ignore this problem, buffer seems to always print as 0.. no changes.
I am very new to this, and expect myself not to know what I am talking about. If you test the game yourself, you'll have to find the address that your chrome is using at the time. But here's the code (I have commented out the WriteProcessMemory and put Read just so I get it working before I write anything):
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
int main() {
int buffer = 0;
LPVOID address = (LPVOID)0x15E7E1B0FB8/*(0x000000000192DFA0 + 0x0000291D8FE04000 + 0x18)*/;
cout << "Begin playing the game and wait for the 0 score to appear" << endl;
HWND window = FindWindow(NULL, "Slope Game - Play online at Y8.com");
if (window) {
cout << "Game found running! You ready to hax?" << endl;
DWORD processID = 11180;
GetWindowThreadProcessId(window, &processID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
if (handle) {
/*string hackedScoreInput = "0";
cout << "Desired Score: " << flush; getline(cin, hackedScoreInput);
int hackedScore = stoi(hackedScoreInput);
int suc = WriteProcessMemory(handle, address, &hackedScore, sizeof(hackedScore), NULL);
if (suc > 0) {
cout << "HAXED!" << endl;
CloseHandle(handle);
}
else {
cerr << GetLastError() << endl;
cerr << hackedScore << " of size: " << sizeof(hackedScore) << endl;
return 3;
}*/
while (true) {
ReadProcessMemory(handle, address, &buffer, sizeof(buffer), NULL);
cout << buffer << " at adress: " << processID << endl;
Sleep(100);
system("CLS");
}
}
else {
cerr << "Could not open the process" << endl;
return 2;
}
}
else {
cerr << "Error! Could not find window!" << endl;
Sleep(3000);
return 1;
}
return 0;
}
What's wrong with the code?
Modern browsers use multiple processes and there is no rule that says that a browser tab HWND has to be owned by the process where the web page "runs".
Some browser implementations might have one main process that hosts the UI including all tabs but the actual web page content might be rendered to a shared bitmap/memory in a different process where it is safe to run scripts etc.
Chrome is open source so you could take a look and see if there is a way to find out which render process renders a certain tab by looking at the child processes command line arguments.
I am trying to connect to the Microsoft SQL Server database with Poco C++ via ODBC. I have tried to find examples, but havent come across any.
I am simply trying to connect to my database with the following code
#include <iostream>
#include <string>
#include "Poco/Data/Session.h"
using namespace std;
using namespace Poco::Data;
int main()
{
cout << "Testing Poco C++ with MS SQL Server" << endl;
const string CONNECTION_STRING("DRIVER={SQL Server};Server=DESKTOP-32BKOVJ\\SQLEXPRESS;Database=Test2;User ID=sa;Password=IaSS1982;Trusted_Connection=yes;");
Session session("ODBC", CONNECTION_STRING);
return 0;
}
Every time I run this code, I get the following assertion failure:
Assertion violation: _connectors.end() != it [in file "src\SessionFactory.cpp", line 70]
How can I create a simple connection to the MS SQL Database using Poco C++ and ODBC and then print some records on the console?
I was referring to the article Poco ODBC and while SQL loop while trying to write this code.
Any help will be greatly appreciated.
Thank you
I am able to connect to my Microsoft SQL Server 2014 Database using Poco C++ library. Once you have the ODBC drivers installed which are a part of the Windows SDK, the following code should do all basic operations such as
- Create
- Read
- Update
- Delete
#include <iostream>
#include <string>
#include <sstream>
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/Session.h"
#include "Poco/Data/ODBC/Connector.h"
using namespace std;
using namespace Poco::Data;
bool AddUser(Session& session, const size_t& USER_ID, const string& FIRST_NAME, const string& LAST_NAME); // [C]reate
void PrintUsers(Session& session); // [R]etrieve
bool UpdateLastName(Session& session, const string& FIRST_NAME, const string& NEW_LAST_NAME); // [U]pdate
bool DeleteUser(Session& session, const size_t& USER_ID); // [D]elete
int main()
{
try
{
cout << "Testing Poco C++ with MS SQL Server" << endl;
Poco::Data::ODBC::Connector::registerConnector();
const string CONNECTION_STRING("DRIVER={SQL Server};Server=DESKTOP-32BKOVJ\\SQLEXPRESS;Database=Test2;User ID=sa;Password=abc");
//const string CONNECTION_STRING("DSN=PocoMsSQLTest;Uid=sa;Pwd=abc");
Session session("ODBC", CONNECTION_STRING);
if (session.isConnected())
{
PrintUsers(session);
cout << "\n" << endl;
AddUser(session, 5, "Loki", "Moki");
PrintUsers(session);
cout << "\n" << endl;
UpdateLastName(session, "Loki", "Poki");
PrintUsers(session);
cout << "\n" << endl;
DeleteUser(session, 5);
PrintUsers(session);
cout << "\n" << endl;
}
else
{
cerr << "Session not able to connect" << endl;
}
}
catch (const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
////////////////////////////////////////////////////////
Poco::Data::ODBC::Connector::unregisterConnector();
return 0;
}
// Create
bool AddUser(Session& session, const size_t& USER_ID, const string& FIRST_NAME, const string& LAST_NAME)
{
Statement select(session);
stringstream ss;
ss << "INSERT INTO Users (UserID, FirstName, LastName) VALUES (";
ss << USER_ID << ", " << "\'" << FIRST_NAME << "\'" << ", " << "\'" << LAST_NAME << "\')";
const string& SQL = ss.str();
select << SQL;
return select.execute();
}
// Retrieve
void PrintUsers(Session& session)
{
Statement select(session);
select << "SELECT * FROM Users";
select.execute();
RecordSet rs(select);
bool more = rs.moveFirst();
if (more)
{
cout << rs.columnName(0) << "\t" << rs.columnName(1) << "\t" << rs.columnName(2) << endl;
}
while (more)
{
cout << rs[0].convert<string>() << "\t" << rs[1].convert<string>() << "\t\t" << rs[2].convert<string>() << endl;
more = rs.moveNext();
}
}
// Update
bool UpdateLastName(Session& session, const string& FIRST_NAME, const string& NEW_LAST_NAME)
{
Statement select(session);
stringstream ss;
ss << "UPDATE Users SET LastName=" << "\'" << NEW_LAST_NAME << "\'" << " WHERE FirstName=" << "\'" << FIRST_NAME << "\'";
const string& SQL = ss.str();
select << SQL;
return select.execute();
}
// Delete
bool DeleteUser(Session& session, const size_t& USER_ID)
{
Statement select(session);
stringstream ss;
ss << "DELETE FROM Users WHERE UserID = " << USER_ID;
const string& SQL = ss.str();
select << SQL;
return select.execute();
}
The CONNECTION_STRING that I am using is using the ODBC drivers directly to connect to the database. If you want to use a DSN to connect to the database then comment this CONNECTION_STRING and uncomment the one below.
I did a little bit of research on what is DSN and how to create it in Windows 10. My findings are given below.
What is a DSN?
See https://en.wikipedia.org/wiki/Data_source_name
Creating an ODBC Data Source Name (DSN)
1. Windows 10 search for ODBC
2. Click on Set up ODBC data sources (32-bit)
3. Under the tab "User DSN", click Add
Create New Data Source wizard will start.
4. Select SQL Server and click Finish
5. In the next window
- Give a name. This is the DSN
- Give description
- Click the drop down associated with Server
- Wait for a few seconds
- Databases on your computer or network will show
- Select the database server you want to connect to.
- Click Next
6. In the next window
- Select with SQL Server Authentication
- Enter your Login ID (Username) and Password for that database
- Click Next
7. In the next window
- Select "Change the default database to:" the database you want to connect.
- Click Next
8. In the next window you don't have to change anything just click Finish.
9. A new window appears which has all your DSN information.
10. To test the DSN connection click on "Test Data Source..."
- If everything is ok, a new window appears "TESTS COMPLETED SUCCUSSFULLY!"
- Click OK to exit the result window.
11. Click OK again finish the setup.
12. In the main Window under User Data Sources you will see your newly created DSN.
13. Click OK to exit.
Source: https://www.youtube.com/watch?v=ehVFtmhPwxs
I'm trying to connect a micro-controller with my desktop PC via USB-serial cable.
The OS of my desktop PC is Windows 8.1, and USB-serial cable is TTL-232R-3V3. (FTDI)
(Qt version: 5.2.0 beta1, QtCreator Version: 3.0, Compiler: MSVC2012)
Now I'm trying read/write loop-back tests, and that's why RX/TX pin of USB-serial cable are connected with each other.
Here is my code.
#include <QtCore/QCoreApplication>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QtCore/QDebug>
#define PORT_NAME "COM3"
#define BAUDRATE 19600
#define TIMEOUT_MS 1000
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSerialPort pSerial(PORT_NAME);
const char strMsg[] = "#1:Send data line \n #2:Send data line\n #3:Send data line end\n";
char strBuf[256];
qint64 nByte;
if(pSerial.open(QIODevice::ReadWrite)){
pSerial.setBaudRate(BAUDRATE);
qDebug() << "OPEN PASS";
pSerial.write(strMsg);
pSerial.flush();
if(pSerial.waitForBytesWritten(TIMEOUT_MS)){
qDebug() << "WRITE PASS";
}
pSerial.waitForReadyRead(TIMEOUT_MS);
while(true){
if( pSerial.canReadLine()){
qDebug() << "CAN READ LINE";
nByte = pSerial.readLine(strBuf,sizeof(strBuf));
qDebug() << "Length: " << nByte;
qDebug() << "Read data: " << strBuf;
}
}
pSerial.close();
} else {
qDebug() << "OPEN FAIL\n";
}
return a.exec();
}
When the program starts to run, the result is different than I expected.
Only first line of sent data can be received. So, "Read data: #1 Send data line" is printed
on console. But the rest of sent data will never be received. Does anyone know why?
Any help would be appreciated.
Thanks in advance.
EDIT: I revised my code according to Papp's comment.Then it works as I expected.
All sent message has been received.
Does it mean I misunderstand the usage about readLine() or canReadLine()?
// while(true){
// if( pSerial.canReadLine()){
// qDebug() << "CAN READ LINE";
// nByte = pSerial.readLine(strBuf,sizeof(strBuf));
// qDebug() << "Length: " << nByte;
// qDebug() << "Read data: " << strBuf;
// }
// }
pSerial.waitForReadyRead(TIMEOUT_MS);
QByteArray readData = pSerial.readAll();
while (pSerial.waitForReadyRead(TIMEOUT_MS)) {
readData.append(pSerial.readAll());
}
qDebug() << "Read data: " << readData;
EDIT 2nd time : Following code also works for me.
while(true){
if( pSerial.waitForReadyRead(TIMEOUT_MS) && pSerial.canReadLine()){ // I revised this line
qDebug() << "CAN READ LINE";
nByte = pSerial.readLine(strBuf,sizeof(strBuf));
qDebug() << "Length: " << nByte;
qDebug() << "Read data: " << strBuf;
qDebug() << "Error Message: " << pSerial.errorString();
}
}
That is because you need to read in a loop like this:
QByteArray readData = serialPort.readAll();
while (serialPort.waitForReadyRead(5000))
readData.append(serialPort.readAll());
Please see the creadersync example for the details what I added to 5.2. You can also check the creaderasync example for non-blocking operation.
To be fair, we have not tested readLine that much, but it works for me on Unix, so does it on Windows for someone else.
The mistake that you've made is expecting to receive all the sent data when waitForReadyRead returns. When waitForReadyRead finishes, all you're guaranteed is some data being available to be read. It may be as little as one character, not necessarily a whole line.
The loop from your last modification is the almost correct way to do it. You should nest reading of the lines in a separate loop. The following code is how it should be done, and agrees with the semantics of QIODevice:
while (pSerial.waitForReadyRead(TIMEOUT_MS)) {
while (pSerial.canReadLine()) {
qDebug() << "NEW LINE";
QByteArray line = pSerial.readLine();
qDebug() << "Length: " << line.size();
qDebug() << "Read data: " << line;
qDebug() << "Error Message: " << pSerial.errorString();
}
}
qDebug << "TIMED OUT";
Note that none of this code should even run in the GUI thread. Ideally you should move it to a QObject, use the signals emitted by QIODevice (and thus QSerialPort), and move that object to a separate thread.
The GUI thread can sometimes block for long periods of time, it's not normally desirable to have it disturb the timeliness of your device communication. Similarly, you don't want device timeouts to block the GUI thread. Both are equally bad and are a very common source of bad user experience. Qt makes multithreading very easy - leverage it for your user's sake, and do it properly.
On Linux I have to do it this way to receive ASCII text ending with '\n'
QByteArray readData = pSerial.readAll();
while (readData[readData.length() - 1] != '\n') {
pSerial.waitForReadyRead(5000);
readData.append(pSerial.readAll());
}
QString result(readData);
QSerialPort::readLine() doesn't work for me either