I have created a Windows Form App for our works Windows Tablets (windows 10) to track location.
The class I have created is below:
class LocationServices
{
private GeoCoordinateWatcher myWatcher;
private bool fgWatcherStarted = false;
public LocationServices()
{
myWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
fgWatcherStarted = myWatcher.TryStart(true, System.TimeSpan.FromMilliseconds(1000));
}
public LatLon GetDeviceLocation()
{
LatLon myReturn = new LatLon();
System.Device.Location.GeoCoordinate myPosition = new System.Device.Location.GeoCoordinate();
try
{
if (!fgWatcherStarted)
{
fgWatcherStarted = myWatcher.TryStart(true, System.TimeSpan.FromMilliseconds(1000));
}
myPosition = myWatcher.Position.Location;
if (myPosition.IsUnknown)
{
myReturn.Latitude = 0;
myReturn.Longitude = 0;
myReturn.strMessage = "Unknown Position";
}
else
{
myReturn.Latitude = myPosition.Latitude;
myReturn.Longitude = myPosition.Longitude;
myReturn.strMessage = myPosition.Course.ToString();
}
}
catch (Exception ex)
{
myReturn.Latitude = 0;
myReturn.Longitude = 0;
myReturn.strMessage = ex.Message.ToString();
}
return myReturn;
}
}
In my code I am running through every few seconds and getting the location by calling the class above.
If I am connected to wifi (running from my desk) it gets the location instantly and works as expected, but from the device it returns 0 for a significant amount of time and then suddenly starts working and works perfectly fine with no issues.
Is there anything I can do to make this start quicker? I initially thought it could be the location/signal but I have tried loading in the same place and leaving it and once it initialises it works perfectly but it's the initial coordinates that take ages to load.
Looks as though there needs to be a position change for it to return a value, see the answer here: https://stackoverflow.com/a/52910209/6639187
Not quite sure about your way of getting the coordinates, I used to do the following method - hope this helps (run it in a console app and check as follows)
class Program
{
private static GeoCoordinateWatcher Watcher;
static void Main(string[] args)
{
Watcher = new GeoCoordinateWatcher();
Watcher.StatusChanged += Watcher_StatusChanged;
Watcher.Start();
Console.ReadLine();
}
static void Watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
if (e.Status == GeoPositionStatus.Ready)
{
if (Watcher.Position.Location.IsUnknown)
{
Console.Write("Cannot find location");
}
else
{
Console.WriteLine("Lat: " + Watcher.Position.Location.Latitude.ToString());
Console.WriteLine("Lon: " + Watcher.Position.Location.Longitude.ToString());
}
}
}
}
Related
I've been working on a project that reads a person's heart rate from a Polar H7 hrm. I've been successful in connecting the device and getting the heart rate which the program shows as text in the UI. However, there are instances where the program suddenly stops getting input from the device.
I have already checked the connection of the device to my Win 10 laptop and saw that it was stable, there were also no exceptions getting thrown by the program. The text simply stops changing.
Here is the code I've written:
public sealed partial class MainPage : Page
{
private GattDeviceService device;
public MainPage()
{
this.InitializeComponent();
init();
}
async void init()
{
var devices = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.HeartRate));
Status.Text = devices.Count.ToString();
device = await GattDeviceService.FromIdAsync(devices[0].Id);
enableSensor();
}
private async void enableSensor()
{
IReadOnlyList<GattCharacteristic> characteristicList;
characteristicList = device.GetAllCharacteristics();
if (characteristicList != null)
{
GattCharacteristic characteristic = characteristicList[0];
if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
{
characteristic.ValueChanged += SendNotif;
await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
}
}
}
async void SendNotif(GattCharacteristic sender, GattValueChangedEventArgs eventArgs)
{
if (eventArgs.CharacteristicValue.Length != 0) {
byte[] hrData = new byte[eventArgs.CharacteristicValue.Length];
DataReader.FromBuffer(eventArgs.CharacteristicValue).ReadBytes(hrData);
var hrValue = ProcessData(hrData);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Status.Text = hrValue.ToString();
});
}
}
private int ProcessData(byte[] data)
{
// Heart Rate profile defined flag values
const byte heartRateValueFormat = 0x01;
byte currentOffset = 0;
byte flags = data[currentOffset];
bool isHeartRateValueSizeLong = ((flags & heartRateValueFormat) != 0);
currentOffset++;
ushort heartRateMeasurementValue;
if (isHeartRateValueSizeLong)
{
heartRateMeasurementValue = (ushort)((data[currentOffset + 1] << 8) + data[currentOffset]);
currentOffset += 2;
}
else
{
heartRateMeasurementValue = data[currentOffset];
}
return heartRateMeasurementValue;
}
}
I'm trying out C# for Raspberry through Visual Studio and windows 10 IoT. Just took me an eternity to make everything work, but I slowly got there. I got my leds workings following their outdated 2 years old tutorials. I'm now trying to add a button to my breadboard to turn the leds on and off... Sadly, This doesn't work at all. It's like ValueChanged is never triggered.
I followed this guide: https://developer.microsoft.com/en-us/windows/iot/samples/pushbutton
My button is wired like: 1 pin directly to ground and the other one to GPIO18 (Pin 12)
Before thequestion comes, yes I did try using GPIO5 too. I just went back to GPIO18 as it was working on my python script before.
This is the code I'm trying to run, but having button problems (leds are fine):
public sealed class StartupTask : IBackgroundTask
{
private GpioController gpio = GpioController.GetDefault();
private GpioPin pinRed;
private GpioPin pinBlue;
private GpioPin pinButton;
private GpioPinValue pinValue;
private const int BLUE_PIN = 19;
private const int RED_PIN = 26;
private const int BUTTON_PIN = 18;
public void Run(IBackgroundTaskInstance taskInstance)
{
Debug.WriteLine("initialising");
InitGpio();
if (pinRed != null)
{
pinValue = GpioPinValue.High;
pinRed.Write(pinValue);
pinBlue.Write(pinValue);
}
}
private void InitGpio()
{
gpio = GpioController.GetDefault();
if (gpio == null)
{
pinRed = null;
pinBlue = null;
pinButton = null;
Debug.WriteLine("Failed starting GPIO");
return;
}
pinValue = GpioPinValue.Low;
pinRed = gpio.OpenPin(RED_PIN);
pinRed.Write(pinValue);
pinRed.SetDriveMode(GpioPinDriveMode.Output);
pinBlue = gpio.OpenPin(BLUE_PIN);
pinBlue.Write(pinValue);
pinBlue.SetDriveMode(GpioPinDriveMode.Output);
pinButton = gpio.OpenPin(BUTTON_PIN);
if (pinButton.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
{
Debug.WriteLine("Is supported");
pinButton.SetDriveMode(GpioPinDriveMode.InputPullUp);
}
else
{
Debug.WriteLine("Not supported");
pinButton.SetDriveMode(GpioPinDriveMode.Input);
}
pinButton.DebounceTimeout = TimeSpan.FromMilliseconds(50);
pinButton.ValueChanged += buttonValueChange;
Debug.WriteLine("GPIO initialised");
}
private void buttonValueChange(GpioPin sender, GpioPinValueChangedEventArgs e)
{
Debug.WriteLine("here");
if (e.Edge == GpioPinEdge.FallingEdge)
{
Debug.WriteLine("Button push");
pinValue = (pinValue == GpioPinValue.Low) ? GpioPinValue.High : GpioPinValue.Low;
pinRed.Write(pinValue);
pinBlue.Write(pinValue);
}
else
{
Debug.WriteLine("Button release");
}
}
}
Yes, lots of debug lines, as I said, trying out C# on Raspberry (InputPullUp is supported). The "here" in buttonValueChange is never triggered. I did the exact same wiring setup on Python and it worked flawlessly on the same pins.
It is suggested here ValueChanged not firing with C# Win10 Iot that "When the Run method ends, unless a deferral object is created, the Background Application ends."
As such you could try to add this line to your Run code:
var deferral = taskInstance.GetDeferral();
And see if it helps.
So I have been working on my C# project which required to do some serial communication. Everything was working fine until I have one really... weird issue.
So right now I am recieving a code in serial which is stored in myString. Then below where I get the issue which is that if I am not debugging the code then a whole if statement just... get ignored. However when I use a breakpoint it does everything right. For referance everything here works except the part of (*l)
(the rest of the code was removed for needless parts. I can attach more if you guys think it can help.)
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
//
//
this.myDelegate = new AddDataDelegate(AddDataMethod);
//
//
private void Receiver(object sender, SerialDataReceivedEventArgs e)
{
Byte[] str = System.Text.Encoding.ASCII.GetBytes(comPort.ReadExisting());
this.Invoke(this.myDelegate, new Object[]
{
System.Text.Encoding.Default.GetString(str)
});
}
//
private void button2_Click(object sender, EventArgs e)
{
if (connectionStatus.Text == "Connected")
{
comPort.Close();
}
else
{
try
{
comPort.PortName = port;
comPort.BaudRate = baudRate;
comPort.DataBits = dataBits;
comPort.StopBits = (StopBits)stopBits;
comPort.Parity = parity;
comPort.DataReceived += new SerialDataReceivedEventHandler(Receiver);
comPort.Open();
connectionButton.Text = "Disconnect";
connectionStatus.Text = "Connected";
}
catch
{
comPort.Close();
}
}
}
public void AddDataMethod(String myString)
{
try
{
string colorSensorValue;
string distanceSensorValue;
string proximitySwitch;
string limitSwitch;
if (myString.Contains("*c*"))
{
string[] colors;
int red;
int blue;
int green;
int max;
colorSensorValue = myString.Substring(myString.IndexOf("*c*") + 3);
if (colorSensorValue.Contains("*e")) colorSensorValue = colorSensorValue.Substring(0, colorSensorValue.IndexOf("*e*"));
colors = colorSensorValue.Split(',');
red = Convert.ToInt16(colors[0]);
green = Convert.ToInt16(colors[1]);
blue = Convert.ToInt16(colors[2]);
max = Math.Max(red, Math.Max(green, blue));
red = red * 255 / max;
blue = blue * 255 / max;
green = green * 255 / max;
color.BackColor = Color.FromArgb(red,blue,green);
colorSensorTextBox.Text = (colorSensorValue);
}
if (myString.Contains("*d"))
{
distanceSensorValue = myString.Substring(myString.IndexOf("*d*") + 3);
if (distanceSensorValue.Contains("*e")) distanceSensorValue = distanceSensorValue.Substring(0, distanceSensorValue.IndexOf("*e*"));
distanceSensorTextBox.Text = (distanceSensorValue);
}
if (myString.Contains("*l"))
{
limitSwitch = myString.Substring(myString.IndexOf("*l*") + 3);
if (limitSwitch.Contains("*e")) limitSwitch = limitSwitch.Substring(0, limitSwitch.IndexOf("*e*"));
limitRead.Text = limitSwitch;
}
if (myString.Contains("*p"))
{
proximitySwitch = myString.Substring(myString.IndexOf("*p*") + 3);
if (proximitySwitch.Contains("*e")) proximitySwitch = proximitySwitch.Substring(0, proximitySwitch.IndexOf("*e*"));
proximityRead.Text = proximitySwitch;
}
comPort.BaseStream.Flush();
}
catch
{
}
}
Example of myString:
*c*96,84,75*e**d*25.5*e**p*0*e**l*0*e*
so it will be read as:
colors: 96 , 84 , 75 (happens right!)
distance: 25.5 (happens right!)
prox : 0 (happens right!)
limit : 0 (doesnt happen..)
note that order of both sent and received data doesn't change which one (limit) that doesn't work unless I breakpoint
According the SerialPort: class information in MSDN:
The DataReceived event is raised on a secondary thread when data is
received from the SerialPort object. Because this event is raised on a
secondary thread, and not the main thread, attempting to modify some
elements in the main thread, such as UI elements, could raise a
threading exception. If it is necessary to modify elements in the main
Form or Control, post change requests back using Invoke, which will do
the work on the proper thread.
You should use use this form:
this.Invoke(this.AddDataMethod, new Object[] { The_Received_String });
}
I'm using both Unity Ads and Vungle to my game. I installed them using their .unitypackage.
I already finished the codes for displaying ads from them alternately. My problem now is how to stop them from fetching/loading after closing their 1st ads? Or have the option to stop the fetching while it fetches.
It make my game crashes due to memory pressure since 2 ads are already in the memory plus the resources for my game.
I browsed the source codes and can't find any API to stop fetching or unload a waiting-to-be-displayed ads. I looked on their documentations but there's no detail to do that.
Here is my current code:
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;
public class AdsMngr : MonoManager<AdsMngr> {
enum AdsEngine{
VUNGLE,
UNITY_ADS,
MAXNUM
};
enum AdsStatus{
IDLE,
WAITING,
SHOWING,
MAXNUM
}
AdsEngine m_curAdsEngine = AdsEngine.UNITY_ADS;
AdsStatus m_curAdsStatus = AdsStatus.IDLE;
#if UNITY_IPHONE || UNITY_ANDROID
protected override void Awake(){
base.Awake ();
m_curAdsEngine = AdsEngine.UNITY_ADS; //VUNGLE;
SetupAdsCallback ();
}
protected override void OnDestroy(){
base.OnDestroy();
UnsetupAdsCallback();
}
void SetNextAdEngine (){
m_curAdsEngine = (AdsEngine)((int)(m_curAdsEngine + 1) % (int)AdsEngine.MAXNUM);
}
void Update(){
if (m_curAdsStatus == AdsStatus.WAITING) {
Debug.Log ("Waiting for ads to load: "+m_curAdsEngine+"\n");
bool bHasReadyAds = false;
switch(m_curAdsEngine){
case AdsEngine.VUNGLE: if( Vungle.isAdvertAvailable()){bHasReadyAds = true;} break;
case AdsEngine.UNITY_ADS: if( Advertisement.isReady() ){bHasReadyAds = true;} break;
}
if (bHasReadyAds) {
LoadingOverlay.Instance.Close();
PromptOverlay.Instance.Close();
ShowAd ();
}
}
}
public void StartAd(){
LoadingOverlay.Instance.Open();
//---start refetching/recaching the ads here
switch(m_curAdsEngine){
case AdsEngine.VUNGLE: {
Vungle.init( "mygame_forAndroid", "mygame_forIOS" );
}break;
case AdsEngine.UNITY_ADS: {
if (Advertisement.isSupported) {
//Advertisement.allowPrecache = true;
Advertisement.Initialize ("12345", true);
Debug.Log("Advertisement Initialized.\n");
} else {
Debug.Log("Platform not supported\n");
}
}break;
}
m_curAdsStatus = AdsStatus.WAITING;
}
public void StopWaitingAds(){
m_curAdsStatus = AdsStatus.IDLE;
//TODO: cancel the loading of ads.
//xxx: test code only
SetNextAdEngine ();
}
public void ShowAd(){
switch(m_curAdsEngine){
case AdsEngine.VUNGLE: {
Debug.Log("*** Vungle Ads is available. Now playing...\n");
Vungle.playAd();
Vungle.setSoundEnabled(false);
}break;
case AdsEngine.UNITY_ADS: {
Debug.Log("*** Unity Ads is available. Now playing...\n");
Advertisement.Show(null, new ShowOptions {
pause = true,
resultCallback = result => {
Debug.Log(result.ToString());
onAdEndedEvent();
}
});
}break;
}
m_curAdsStatus = AdsStatus.SHOWING;
}
#region Optional: Example of Subscribing to All Events
void SetupAdsCallback()
{
Vungle.onAdStartedEvent += onAdStartedEvent;
Vungle.onAdEndedEvent += onAdEndedEvent;
Vungle.onAdViewedEvent += onAdViewedEvent;
Vungle.onCachedAdAvailableEvent += onCachedAdAvailableEvent;
}
void UnsetupAdsCallback()
{
Vungle.onAdStartedEvent -= onAdStartedEvent;
Vungle.onAdEndedEvent -= onAdEndedEvent;
Vungle.onAdViewedEvent -= onAdViewedEvent;
Vungle.onCachedAdAvailableEvent -= onCachedAdAvailableEvent;
}
void onAdStartedEvent()
{
Debug.Log( "onAdStartedEvent" );
}
void onAdEndedEvent()
{
Debug.Log( "onAdEndedEvent" );
EndGameRewardOverlay.Instance.SetMultiplier(2);
EndGameRewardOverlay.Instance.Open();
if (m_curAdsEngine == AdsEngine.VUNGLE) {
Vungle.setSoundEnabled(true);
}
m_curAdsStatus = AdsStatus.IDLE;
SetNextAdEngine();
}
void onAdViewedEvent( double watched, double length )
{
Debug.Log( "onAdViewedEvent. watched: " + watched + ", length: " + length );
}
void onCachedAdAvailableEvent()
{
Debug.Log( "onCachedAdAvailableEvent" );
}
#endregion
#endif
}
Unity Ads and Vungle handle Ad Cacheing them self and there is not way to stop it. It is done as both networks show video Ads and video Ads take time to buffer if not pre cached before displaying.
It is about TWAINdotNet library. I have spent last 24 hours trying to do basic virtual scanner experiment in C#/WPF/VS2010. I have already downloaded and installed virtual scanner driver from http://sourceforge.net/projects/twain-samples/files/ and it appears just fine in the list of available TWAIN data sources. Interestingly, the sample application that is available on this page works perfectly fine with this driver too. The problem occurs only when I try to use it through C#/WPF.
Specifically, calling DsUserInterface using Message.EnableDS fails for God-knows what reason. It fails in all cases whether I ask it to show UI or not. Similarly DsImageLayout call also results in Failure when trying to set the scan area. Last but not the least, trying to set measurement units to inches (or whatever) also doesn't take effect. The call doesn't fail, but the previous value remains intact.
Here's the code in case I may be doing something wrong:
public partial class MainWindow : Window
{
TwainDotNet.Wpf.WpfWindowMessageHook mTwnHook;
TwainDotNet.Twain mTWN;
TwainDotNet.ScanSettings setting = new TwainDotNet.ScanSettings();
public MainWindow()
{
InitializeComponent();
}
private void btnScan_Click(object sender, RoutedEventArgs e)
{
InitializeTWAIN();
mTWN.ScanningComplete += twn_ScanningComplete;
mTWN.TransferImage += twn_TransferImage;
mTWN.StartScanning(setting);
}
private void InitializeTWAIN()
{
mTwnHook = new TwainDotNet.Wpf.WpfWindowMessageHook(this);
mTWN = new TwainDotNet.Twain(mTwnHook);
setting.UseAutoFeeder = true;
setting.UseDocumentFeeder = true;
setting.UseDuplex = true;
setting.TransferCount = 1;
setting.Page = new TwainDotNet.PageSettings()
{
Orientation = TwainDotNet.TwainNative.Orientation.Auto,
Size = TwainDotNet.TwainNative.PageType.UsLetter
};
setting.Area = new TwainDotNet.AreaSettings(TwainDotNet.TwainNative.Units.Millimeters, 0f, 0f, 279.4f, 215.9f);
setting.Resolution = new TwainDotNet.ResolutionSettings()
{
ColourSetting = TwainDotNet.ColourSetting.Colour,
Dpi = 100
};
setting.ShouldTransferAllPages = true;
setting.ShowTwainUI = false;
}
void twn_TransferImage(object sender, TwainDotNet.TransferImageEventArgs e)
{
//save image
}
void twn_ScanningComplete(object sender, TwainDotNet.ScanningCompleteEventArgs e)
{
if (e.Exception != null)
MessageBox.Show(e.Exception.Message);
}
}