WP7使用模拟器时模拟Microsoft.Devices.Sensors.Compass

时间:2012-02-21 02:17:55

标签: windows-phone-7 windows-phone-7.1

我希望能够在模拟器中运行Windows Phone 7.1时模拟指南针传感器。

在这个阶段,我并不特别关心指南针返回的数据。只是在使用模拟器测试相关代码时,我可以反对某些东西。

我知道我可以部署到我的dev解锁手机来测试罗盘功能,但我发现通过Zune软件的连接经常丢失。

更新

我已经开始研究创建自己的包装类,它可以在运行调试版本时模拟指南针,并且不支持指南针。

Microsoft.Devices.Sensors.CompassReading struct让我有点难过。因为它是一个只能在内部设置属性的结构,所以我不能从它继承来提供我自己的值。我查看了using reflection to brute force some values in,但Silverlight doesn't appear to allow it

1 个答案:

答案 0 :(得分:2)

你已经注意到我遇到了类似的问题。当我嘲笑指南针传感器时,我也遇到了困难,因为你不能从现有的类中继承并编写自己的逻辑。因此,我编写了自己的指南针界面,这是我的应用程序使用的唯一指南针功能。然后有两个实现,一个WP7指南针功能包装器和我的模拟指南针。

我可以告诉你一些代码,但不是在周末之前因为我不在我的发展机器atm。

修改

你已经得到了它但是对于有同样问题的其他人我将添加我的代码。正如我已经说过的,我编写了一个接口和两个实现,一个用于电话和一个模拟实现。

指南针界面

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
}

使用过的数据类和事件参数

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实施

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
}

模拟实施

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

}