I'm working on a WinRT/C++ application that uses Windows APIs to access to RFCOMM Bluetooth and looks for nearby devices. Then I try to create a service in order to create a connection, so I run:
RfcommDeviceService service = RfcommDeviceService::FromIdAsync(currId).get();
However, the FromIdAsync method returns NULL since, according to the documentation:
If a store app has not declared the right capabilities or the user does not grant consent, the method returns a null object.
The solutions I found online all require to add a <Capabilities> tag to the Package.appxmanifest file. However, I do not have such file, since I'm working on a standard Console app.
Is there another way to grant permissions to my app? Alternatively, can I include manually a Package.appxmanifest file so that I can access the Bluetooth? Or I am completely missing the point here and the error is caused by something else?
EDIT: Minimal reproducible example:
// Store all the devices
vector<DeviceInformation> devices;
// Replace targetAddress with Bluetooth address to pair
string targetAddress = "XX:XX:XX:XX:XX:XX";
// AQS string for RFCOMM devices
hstring selectorString = to_hstring("System.Devices.DevObjectType:=5 AND System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\" AND((System.Devices.Aep.IsPaired: = System.StructuredQueryType.Boolean#True OR System.Devices.Aep.IsPaired: = System.StructuredQueryType.Boolean#False) OR System.Devices.Aep.Bluetooth.IssueInquiry: = System.StructuredQueryType.Boolean#False)");
// Create watcher
DeviceWatcher deviceWatcher = DeviceInformation::CreateWatcher(selectorString);
// Callback function for event handling
auto OnAddedDevice = [](DeviceWatcher watcher, DeviceInformation deviceInfo)
{
devices.push_back(deviceInfo);
};
// New Bluetooth device detected -> callback
deviceWatcher.Added(OnAddedDevice);
// Start watcher
deviceWatcher.Start();
std::cout << "Performing device scan...\n" << endl;
Sleep(4000);
// Stop scanning
deviceWatcher.Stop();
// Print results
for (int i = 0; i < devices.size(); i++) {
string name = to_string(devices[i].Name());
string address = getAddress(devices[i]);
std::cout << "(" << address << ")" << "\t" << name << endl;
}
std::cout << endl;
// Look for target device among the scanned ones
for (int i = 0; i < devices.size(); i++) {
string address = getAddress(devices[i]);
// Match found
if (address == targetAddress) {
// Get ID
auto currId = devices[i].Id();
// Create Service [HERE, FROM IDASYNC RETURNS NULL]
RfcommDeviceService service = RfcommDeviceService::FromIdAsync(currId).get();
// Try to get information about the created service [LAUCHES EXCEPTION SINCE service IS NULL]
auto protectionLevel = service.ProtectionLevel();
}
}
Helper function getAddress is used to parse the device ID
string getAddress(DeviceInformation device) {
string id = to_string(device.Id());
string address = "";
for (int i = 37; i < id.length(); i++) {
address += toupper(id[i]);
}
return address;
}
Related
I have an std::set that contains unique values. I have an std::queue that holds the same values
in order to age the values in std::set.
I'd like to use a timer to determine when to pop a value from the queue and then erase the value from the set.
The timer is created/started every time data is added to an empty set/queue.
If data is added to a non-empty set/queue, no change is made to the timer.
The timer would fire every X milliseconds to execute a function.
The function would pop a value from the queue then erase that value from the set.
If the set/queue is now empty the timer would stop.
If the set/queue is not empty, no change is made to the timer.
This program runs in Windows 10.
Does this way make sense? Is there a better/more efficient/simpler way to age the data?
I've read the docs on Using Timer Queues so I see how the queue and the timers are created and destroyed. What I don't see is a recommendation for starting/stopping timers.
Should I be creating a new TimerQueueTimer to wait for X milliseconds once, run the func and then create a new TimerQueueTimer if the set/queue is not empty?
Should I instead create a single TimerQueueTimer to run periodically X milliseconds but delete it once the set/queue is empty?
Is there a 3rd technique I should use instead?
Here's my example code.
using unsignedIntSet = std::set<std::uint32_t>;
using unsignedIntQ = std::queue<std::uint32_t>;
unsignedIntQ agingQ;
unsignedIntSet agingSet;
HANDLE gDoneEvent = NULL;
HANDLE hTimer = NULL;
HANDLE hTimerQueue = NULL;
VOID CALLBACK ageTimer(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
if (!agingQ.empty())
{
auto c = agingQ.front();
agingSet.erase(c);
agingQ.pop();
if (!agingQ.empty())
{
// rerun CreateTimerQueueTimer() here?
}
}
SetEvent(gDoneEvent);
}
int createTimerForAgingQ()
{
// create timer if it doesn't already exist
if (gDoneEvent == NULL)
{
gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (gDoneEvent == NULL)
{
std::cerr << "CreateEvent() error: " << WSAGetLastError() << std::endl;
return -1;
}
hTimerQueue = CreateTimerQueue();
if (hTimerQueue == NULL)
{
std::cerr << "CreateTimerQueue() error: " << WSAGetLastError() << std::endl;
return -1;
}
if (!CreateTimerQueueTimer(&hTimer, hTimerQueue, (WAITORTIMERCALLBACK)ageTimer, NULL, 500, 0, WT_EXECUTEONLYONCE))
{
std::cerr << "CreateTimerQueueTimer() error: " << WSAGetLastError() << std::endl;
return -1;
}
}
}
void addUnique(unsigned char* buffer, int bufferLen)
{
// hash value
auto h = hash(buffer, bufferLen);
// test insert into set
auto setResult = agingSet.emplace(h);
if (setResult.second)
{
// enqueue into historyQ
agingQ.emplace(h);
if (!gDoneEvent) createTimerForAgingQ();
}
}
Research shows that the CreateTimerQueue/CreateTimerQueueTimer may not be the way to go.
Use of ThreadpoolTimer
I am using OMNET 5.0, SUMO-0.25.0 and VEINS-4.4. When a vehicle receive a message; onData() is called. I can get external ID of the current vehicle using mobility->getExternalId(); but how I know the the external ID of wsm message sender
The code for initialize():
void TraCIDemo11p::initialize(int stage) {
BaseWaveApplLayer::initialize(stage);
if (stage == 0) {
mobility = TraCIMobilityAccess().get(getParentModule());
traci = mobility->getCommandInterface();
traciVehicle = mobility->getVehicleCommandInterface();
annotations = AnnotationManagerAccess().getIfExists();
ASSERT(annotations);
getExternalID = mobility->getExternalId();
sentMessage = false;
lastDroveAt = simTime();
findHost()->subscribe(parkingStateChangedSignal, this);
isParking = false;
sendWhileParking = par("sendWhileParking").boolValue();
}
}
The code for onData():
void TraCIDemo11p::onData(WaveShortMessage* wsm) {
std::cout << " I am "<< getExternalID <<"and I received a message from ???? "<<endl;
findHost()->getDisplayString().updateWith("r=16,green");
annotations->scheduleErase(1, annotations->drawLine(wsm->getSenderPos(), mobility->getPositionAt(simTime()), "blue"));
if (mobility->getRoadId()[0] != ':')
traciVehicle->changeRoute(wsm->getWsmData(), 9999);
if (!sentMessage)
sendMessage(wsm->getWsmData());
}
A vehicle can be represented by two identifiers, either that one gotten from SUMO (i.e., calling getExternalId()) or that one of veins (myId normally), the one used in WaveShortMessage after calling getSenderAddress() is myId so I suggest that you focus on that last one.
Take a look on these two files to get a better idea on the used identifier and the existing methods: "BaseWaveApplLayer.h/.cc" & "WaveShortMessage_m.h/.cc"
I hope this helps.
When trying to start a new waypoint mission while one is already in progress, I usually get a OpenProtocol::ErrorCode::MissionACK::WayPoint::DATA_NOT_ENOUGH error when I try to upload the first waypoint. Strangely, if I stop the mission afterwards and try uploading again, it works.
Unfortunately, I couldn't find any detailed documentation on what this error means.
Here's my code (note that it's the onboard SDK, not the mobile SDK; the code is Java calling into native code; interface generated by SWIG):
public void uploadWaypointMissionImpl(#NonNull DroneMission mission) throws DroneException{
WayPointInitSettings wpis = newMissionSettings(mission);
MissionManager missionManager = vehicle.getMissionManager();
WaypointMission wptMission;
int wpcount = missionManager.getWayptCounter();
if (wpcount > 0){
wptMission = missionManager.getWpMission();
wptMission.stop(REQUEST_TIMEOUT_SECONDS);
wptMission.init(wpis, REQUEST_TIMEOUT_SECONDS);
} else{
missionManager.initWaypoint(wpis, REQUEST_TIMEOUT_SECONDS));
wptMission = missionManager.getWpMission();
}
if (wptMission == null)
throw new DroneException("Failed to initialize mission manager");
int pointCount = mission.getNavPoints().size();
logger.i("Waypoint mission created, uploading %d points", pointCount);
for (int i = 0; i < pointCount; ++i){
WayPointSettings wp = newWayPointSettings(mission, i);
wptMission.uploadIndexData(wp, REQUEST_TIMEOUT_SECONDS).getAck(); // <-- ERROR HERE
}
}
private static WayPointInitSettings newMissionSettings(#NonNull DroneMission mission){
WayPointInitSettings wpis = new WayPointInitSettings();
wpis.setMaxVelocity(mission.getVelocityMps());
wpis.setIdleVelocity(mission.getVelocityMps());
wpis.setTraceMode((short)(!mission.isInPlace() && Prefs.drone.traceMode().get() ? 1 : 0));
wpis.setRCLostAction((short)(Prefs.drone.rcLostMode().get() ? 1 : 0));
wpis.setGimbalPitch((short)(Prefs.drone.gimbalPitchAutoMode().get() ? 1 : 0));
wpis.setYawMode((short)0);
wpis.setExecutiveTimes((short)1);
wpis.setFinishAction((short)4);
wpis.setLatitude(0.0);
wpis.setLongitude(0.0);
wpis.setAltitude(0.0f);
wpis.setIndexNumber((short)mission.getNavPoints().size());
Uint8Array reserved = new Uint8Array(16);
for (int i = 0; i < 16; ++i){
reserved.setitem(i, (short)0);
}
wpis.setReserved(reserved.cast());
return wpis;
}
private static WayPointSettings newWayPointSettings(#NonNull DroneMission mission, int index){
WayPointSettings wp = new WayPointSettings();
wp.setDamping(Prefs.drone.dampingDistanceM().get());
wp.setGimbalPitch(Prefs.drone.gimbalPitch().get().shortValue());
wp.setYaw(Prefs.drone.yawDeg().get().shortValue());
wp.setTurnMode((short)(Prefs.drone.turnModeCounterClockwise().get() ? 1 : 0));
wp.setActionTimeLimit(100);
wp.setHasAction((short)0);
wp.setActionNumber((short)0);
wp.setActionRepeat((short)0);
Uint8Array commandList = new Uint8Array(16);
Uint16Array commandParameter = new Uint16Array(16);
for (int i = 0; i < 16; ++i){
commandList.setitem(i, (short)0);
commandParameter.setitem(i, 0);
}
wp.setCommandList(commandList.cast());
wp.setCommandParameter(commandParameter.cast());
NavPoint point = mission.getNavPoints().get(index);
wp.setLongitude(point.getLocation().getLngRad());
wp.setLatitude(point.getLocation().getLatRad());
wp.setAltitude((float)Math.ceil(point.getCruisingAltitude() - mission.getTakeoffAltitudeMeters()));
wp.setIndex((short)index);
return wp;
}
Waypoint mission needs a minimum of 3 waypoints when i tried it on an android device, try adding 2 more points but note that they must have 1 meter distance between each point
Edit: I added code for making waypoints and adding them to a list
// Create a waypoint instance
Waypoint mWaypoint1 = new Waypoint(Latitude, Longitude, altitude);
//check if the mission's builder is null
if (waypointMissionBuilder != null) {
waypointList.add(mWaypoint1);
waypointMissionBuilder.waypointList(waypointList).
waypointCount(waypointList.size());
}
else {
waypointMissionBuilder = new WaypointMission.Builder();
waypointList.add(mWaypoint1);
waypointMissionBuilder.waypointList(waypointList).
waypointCount(waypointList.size());
}
You need to make a waypoint instance which has Lat,Long,Alt. give it the correct parameters and add it to the list then use the builder to config, upload and start the mission. In case the list's size is 2 or less the mission will give you a djiError when trying to use the config function.
Hi,maybe you need to call the "wptMission.stop"before you start a new waypoint mission.All the data of this mission you write is uploaded to the flight controller,only when you call the "wptMission.stop",the flight controller will know you want to call other commands.
I need to develop an application in c# that could automatically detect an iPhone when it is connected to the system and read a particular file for the iPhone file system. I basically want this file to be downloaded automatically from device to the PC. I used USBpcap tool that suggests that iTunes connects to phone using some XML format. Any help or insight greatly appreciated. Is there any documentation of Third party APIs that can get me started? There are some applications that can replicate iTunes functionality e.g Copytrans
Is there any protocol or APIs provided by Apple?
I have been digging the internet and found this link Layered communication for iPhone.
Also I am using the LibUsbDotNet libraries for communicating to the usb device(Example). Can any one suggest which EndPoints should be used.
It seems to me that I have to implement usbmuxd in windows application. It is a multilayer protocol. There must be some libraries that implement usbmuxd(I dont think I have to implement the protocol all by my self)
I dont have much idea about iTunes communication as well as USB communication. I am adding as much information as I can(of course with the things I come up with in my R&D). Any help is highly appreciated.
public static DateTime LastDataEventDate = DateTime.Now;
public static UsbDevice MyUsbDevice;
#region SET YOUR USB Vendor and Product ID!
public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(1452, 4768);
#endregion
private void LibUSB()
{
ErrorCode ec = ErrorCode.None;
try
{
// Find and open the usb device.
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
// If the device is open and ready
if (MyUsbDevice == null)
throw new Exception("Device Not Found.");
// If this is a "whole" usb device (libusb-win32, linux libusb)
// it will have an IUsbDevice interface. If not (WinUSB) the
// variable will be null indicating this is an interface of a
// device.
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// This is a "whole" USB device. Before it can be used,
// the desired configuration and interface must be selected.
// Select config #1
wholeUsbDevice.SetConfiguration(1);
// Claim interface #0.
wholeUsbDevice.ClaimInterface(0);
}
// open read endpoint 1.
UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep03);
// open write endpoint 1.
UsbEndpointWriter writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep02);
int bytesWritten;
ec = writer.Write(usbmux_header.GetBytes(), 2000, out bytesWritten);
if (ec != ErrorCode.None)
throw new Exception(UsbDevice.LastErrorString);
byte[] readBuffer = new byte[1024];
while (ec == ErrorCode.None)
{
int bytesRead;
// If the device hasn't sent data in the last 100 milliseconds,
// a timeout error (ec = IoTimedOut) will occur.
ec = reader.Read(readBuffer, 10000, out bytesRead);
if (ec == ErrorCode.Win32Error)
throw new Exception("port not open");
if (bytesRead == 0)
throw new Exception("No more bytes!");
// Write that output to the console.
Console.Write(Encoding.Default.GetString(readBuffer, 0, bytesRead));
}
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine((ec != ErrorCode.None ? ec + ":" : String.Empty) + ex.Message);
}
finally
{
if (MyUsbDevice != null)
{
if (MyUsbDevice.IsOpen)
{
// If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
// it exposes an IUsbDevice interface. If not (WinUSB) the
// 'wholeUsbDevice' variable will be null indicating this is
// an interface of a device; it does not require or support
// configuration and interface selection.
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// Release interface #0.
wholeUsbDevice.ReleaseInterface(0);
}
MyUsbDevice.Close();
}
MyUsbDevice = null;
// Free usb resources
UsbDevice.Exit();
}
}
}
class usbmux_header
{
public static UInt32 length = 10; // length of message, including header
public static UInt32 reserved = 0; // always zero
public static UInt32 type = 3; // message type
public static UInt32 tag = 2; // responses to this query will echo back this tag
public static byte[] GetBytes()
{
byte[] lgth = BitConverter.GetBytes(length);
byte[] res = BitConverter.GetBytes(reserved);
byte[] tpe = BitConverter.GetBytes(type);
byte[] tg = BitConverter.GetBytes(tag);
byte[] retArray = new byte[16];
lgth.CopyTo(retArray, 0);
res.CopyTo(retArray, 4);
tpe.CopyTo(retArray, 8);
tg.CopyTo(retArray, 12);
return retArray;
}
};
I have been trying to send hello packet bytes to iPhone but I am not able to read any response from phone.
To play with ipod you can use SharePodLib
As I understand it, only one client can use the USB connection to iOS at one time. On both macOS and Windows, that one client is usbmux. That library multiplexes TCP connections with higher-level clients, including iTunes, Photos, and (on macOS) the open-source peertalk library.
So on Windows, you wouldn't want to implement your own usbmux, but rather a client that sits on top of that, analogous to peertalk. I haven't seen anything open-source that does this, but a number of developers have accomplished it with their own proprietary software.
If anybody else has pointers about using usbmux on Windows, I'd love to hear about it.
—Dave
You can use imobiledevice-net. It provides a C# API to connect to iOS devices using your PC.
For example, to list all iOS devices connected to your PC, you would run something like this:
ReadOnlyCollection<string> udids;
int count = 0;
var idevice = LibiMobileDevice.Instance.iDevice;
var lockdown = LibiMobileDevice.Instance.Lockdown;
var ret = idevice.idevice_get_device_list(out udids, ref count);
if (ret == iDeviceError.NoDevice)
{
// Not actually an error in our case
return;
}
ret.ThrowOnError();
// Get the device name
foreach (var udid in udids)
{
iDeviceHandle deviceHandle;
idevice.idevice_new(out deviceHandle, udid).ThrowOnError();
LockdownClientHandle lockdownHandle;
lockdown.lockdownd_client_new_with_handshake(deviceHandle, out lockdownHandle, "Quamotion").ThrowOnError();
string deviceName;
lockdown.lockdownd_get_device_name(lockdownHandle, out deviceName).ThrowOnError();
deviceHandle.Dispose();
lockdownHandle.Dispose();
}
I want to upload a photo, from the WP7 by FTP application. If I choose the photo, and click the upload button, the server response: 503 bad sequence of commands.
public static void UploadFile(Stream file, string RemoteFile)
{
SocketAsyncEventArgs socketEventArg2 = new SocketAsyncEventArgs();
Socket socket2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int bytes;
Execute("STOR " + RemoteFile);
AutoResetEvent sendCompleted = new AutoResetEvent(false);
socketEventArg2.Completed += delegate {
sendCompleted.Set();
};
file.Seek(0, SeekOrigin.Begin);
while ((bytes = file.Read(buffer2, 0, buffer2.Length)) > 0)
{
socketEventArg2.SetBuffer(buffer2, 0, bytes);
socket2.SendAsync(socketEventArg2);
sendCompleted.WaitOne();
}
file.Close();
}
And this method call:
Stream ss = e.ChosenPhoto;
.
.
for (int i = 0; i < library.Pictures.Count; i++)
{
Stream s = library.Pictures[i].GetImage();
if (s.Length == e.ChosenPhoto.Length)
{
string filename = library.Pictures[i].Name;
MessageBoxResult m = MessageBox.Show(filename, "Upload?", MessageBoxButton.OKCancel);
if (m == MessageBoxResult.OK)
{
Ftp.UploadFile(ss, filename);
}
else
{
return;
}
break;
}
}
The ss variable is a Stream type, the filename variable is a String which is name come into being the remote server.
You have to do more than just call STOR with FTP -- file transfers occur over a separate connection than the command connection. See the response to this question for additional details.
Edit
I just noticed this is for WP7. It looks like you're trying to implement FTP on WP7. Boy are you in for a world of hurt. I have a few suggestions you may consider:
First, the easy, but expensive-up-front way: purchase a third party library that does FTP over sockets such as SecureBlackbox.
Second, the more complex, cheaper-initially-but-possibly-more-expensive-long-term way: consider creating an intermediary web service that accepts the file as a WEB request, then transfers the file using FtpWebRequest server-side. Azure will be your friend there, at least until the uploads start sapping bandwidth.
Third, don't support FTP until FtpWebRequest becomes available for WP7.