WP7 Mock Microsoft.Devices.Sensors.Compass when using the emulator

拥有回忆 提交于 2019-12-12 23:49:09

问题


I'd like to be able to simulate the compass sensor when running a Windows Phone 7.1 in the emulator.

At this stage I don't particularly care what data the compass returns. Just that I can run against something when using the emulator to test the code in question.

I'm aware that I could deploy to my dev unlocked phone to test compass functionality but I've found the connection via the Zune software to drop out frequently.

Update

I've looked into creating my own wrapper class that could simulate the compass when running a debug build and the compass isn't otherwise supported.

The Microsoft.Devices.Sensors.CompassReading struct has me a bit stumpted. Because it is a struct where the properties can only be set internally I can't inherit from it to provide my own values back. I looked at using reflection to brute force some values in but Silverlight doesn't appear to allow it.


回答1:


as you already noticed I had a similar problem. when I mocked the compass sensor, I also had difficulties because you cannot inherite from the existing classes and write your own logic. Therefore I wrote my own compass interface which is the only compass functionality used by my application. Then there are two implementations, one wrapper to the WP7 compass functionalities and my mock compass.

I can show you some code, but not before weekend as I'm not at my delevopment machine atm.

Edit:

You already got it but for other people who have the same problem I'll add my code. As I already said, I wrote an interface and two implementations, one for the phone and a mock implementation.

Compass Interface

public interface ICompass
{
    #region Methods

    void Start();

    void Stop();

    #endregion

    #region Properties

    CompassData CurrentValue { get; }

    bool IsDataValid { get; }

    TimeSpan TimeBetweenUpdates { get; set; }

    #endregion

    #region Events

    event EventHandler<CalibrationEventArgs> Calibrate;

    event EventHandler<CompassDataChangedEventArgs> CurrentValueChanged;

    #endregion
}

Used data classes and event args

public class CompassData
{
    public CompassData(double headingAccurancy, double magneticHeading, Vector3 magnetometerReading, DateTimeOffset timestamp, double trueHeading)
    {
        HeadingAccuracy = headingAccurancy;
        MagneticHeading = magneticHeading;
        MagnetometerReading = magnetometerReading;
        Timestamp = timestamp;
        TrueHeading = trueHeading;
    }

    public CompassData(CompassReading compassReading)
    {
        HeadingAccuracy = compassReading.HeadingAccuracy;
        MagneticHeading = compassReading.MagneticHeading;
        MagnetometerReading = compassReading.MagnetometerReading;
        Timestamp = compassReading.Timestamp;
        TrueHeading = compassReading.TrueHeading;
    }

    #region Properties

    public double HeadingAccuracy { get; private set; }

    public double MagneticHeading { get; private set; }

    public Vector3 MagnetometerReading { get; private set; }

    public DateTimeOffset Timestamp { get; private set; }

    public double TrueHeading { get; private set; }

    #endregion
}

public class CompassDataChangedEventArgs : EventArgs
{
    public CompassDataChangedEventArgs(CompassData compassData)
    {
        CompassData = compassData;
    }

    public CompassData CompassData { get; private set; }
}

WP7 implementation

public class DeviceCompass : ICompass
{
    private Compass _compass;

    #region Implementation of ICompass

    public void Start()
    {
        if(_compass == null)
        {
            _compass = new Compass {TimeBetweenUpdates = TimeBetweenUpdates};
            // get TimeBetweenUpdates because the device could have change it to another value
            TimeBetweenUpdates = _compass.TimeBetweenUpdates;
            // attach to events
            _compass.CurrentValueChanged += CompassCurrentValueChanged;
            _compass.Calibrate += CompassCalibrate;
        }
        _compass.Start();
    }

    public void Stop()
    {
        if(_compass != null)
        {
            _compass.Stop();
        }
    }

    public CompassData CurrentValue
    {
        get { return _compass != null ? new CompassData(_compass.CurrentValue) : default(CompassData); }
    }

    public bool IsDataValid
    {
        get { return _compass != null ? _compass.IsDataValid : false; }
    }

    public TimeSpan TimeBetweenUpdates { get; set; }

    public event EventHandler<CalibrationEventArgs> Calibrate;
    public event EventHandler<CompassDataChangedEventArgs> CurrentValueChanged;

    #endregion

    #region Private methods

    private void CompassCalibrate(object sender, CalibrationEventArgs e)
    {
        EventHandler<CalibrationEventArgs> calibrate = Calibrate;
        if (calibrate != null)
        {
            calibrate(sender, e);
        }
    }

    private void CompassCurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
    {
        EventHandler<CompassDataChangedEventArgs> currentValueChanged = CurrentValueChanged;
        if (currentValueChanged != null)
        {
            currentValueChanged(sender, new CompassDataChangedEventArgs(new CompassData(e.SensorReading)));
        }
    }

    #endregion
}

Mock implementation

public class MockCompass : ICompass
{
    private readonly Timer _timer;
    private CompassData _currentValue;
    private bool _isDataValid;
    private TimeSpan _timeBetweenUpdates;
    private bool _isStarted;
    private readonly Random _random;

    public MockCompass()
    {
        _random = new Random();
        _timer = new Timer(TimerEllapsed, null, Timeout.Infinite, Timeout.Infinite);
        _timeBetweenUpdates = new TimeSpan();
        _currentValue = new CompassData(0, 0, new Vector3(), new DateTimeOffset(), 0);
    }

    #region Implementation of ICompass

    public void Start()
    {
        _timer.Change(0, (int)TimeBetweenUpdates.TotalMilliseconds);
        _isStarted = true;
    }

    public void Stop()
    {
        _isStarted = false;
        _timer.Change(Timeout.Infinite, Timeout.Infinite);
        _isDataValid = false;
    }

    public CompassData CurrentValue
    {
        get { return _currentValue; }
    }

    public bool IsDataValid
    {
        get { return _isDataValid; }
    }

    public TimeSpan TimeBetweenUpdates
    {
        get { return _timeBetweenUpdates; }
        set
        {
            _timeBetweenUpdates = value;
            if (_isStarted)
            {
                _timer.Change(0, (int) TimeBetweenUpdates.TotalMilliseconds);
            }
        }
    }

    public event EventHandler<CalibrationEventArgs> Calibrate;
    public event EventHandler<CompassDataChangedEventArgs> CurrentValueChanged;

    #endregion

    #region Private methods

    private void TimerEllapsed(object state)
    {
        _currentValue = new CompassData(_random.NextDouble()*5,
                                        (_currentValue.MagneticHeading + 0.1)%360,
                                        _currentValue.MagnetometerReading,
                                        new DateTimeOffset(DateTime.UtcNow),
                                        (_currentValue.TrueHeading + 0.1)%360);
        _isDataValid = true;
        EventHandler<CompassDataChangedEventArgs> currentValueChanged = CurrentValueChanged;
        if(currentValueChanged != null)
        {
            currentValueChanged(this, new CompassDataChangedEventArgs(_currentValue));
        }
    }

    #endregion

}


来源:https://stackoverflow.com/questions/9371240/wp7-mock-microsoft-devices-sensors-compass-when-using-the-emulator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!