From 93c1c77fd6bc789aad879ab584aaa44d726d9ebf Mon Sep 17 00:00:00 2001 From: arctus Date: Mon, 19 May 2014 22:05:21 +0300 Subject: [PATCH 1/2] Code cleanup, added additional modules --- Devices/V2/Program.cs | 101 ++- imBMW/Features/Comfort.cs | 68 ++- imBMW/Features/Gates.cs | 195 ++++++ imBMW/Features/Light.cs | 2 - .../Localizations/EnglishLocalization.cs | 3 - imBMW/Features/Localizations/Localization.cs | 13 +- .../Localizations/RussianLocalization.cs | 5 +- imBMW/Features/Menu/BordmonitorMenu.cs | 112 ++-- imBMW/Features/Menu/MenuBase.cs | 45 +- imBMW/Features/Menu/MenuHelpers.cs | 2 - imBMW/Features/Menu/MenuItem.cs | 25 +- imBMW/Features/Menu/MenuScreen.cs | 51 +- imBMW/Features/Menu/RadioMenu.cs | 3 - .../Menu/Screens/BordcomputerScreen.cs | 26 +- imBMW/Features/Menu/Screens/HomeScreen.cs | 53 +- imBMW/Features/Menu/Screens/SettingsScreen.cs | 13 +- imBMW/IO/ISerialPort.cs | 5 - imBMW/IO/SerialInterruptPort.cs | 10 +- imBMW/IO/SerialInterruptPortBase.cs | 6 +- imBMW/IO/SerialPortBase.cs | 42 +- imBMW/IO/SerialPortConfiguration.cs | 49 +- imBMW/IO/SerialPortHub.cs | 28 +- imBMW/IO/SerialPortOptoPair.cs | 2 - imBMW/IO/SerialPortTH3122.cs | 2 - imBMW/IO/SerialTimerInterruptPort.cs | 19 +- imBMW/Multimedia/AudioPlayerBase.cs | 33 +- imBMW/Multimedia/BluetoothOVC3860.cs | 155 ++--- imBMW/Multimedia/IAudioPlayer.cs | 2 - imBMW/Multimedia/MultiplexorTDA7313.cs | 3 - imBMW/Multimedia/iPodViaHeadset.cs | 70 ++- imBMW/Shields/BluetoothOVC3860Shield.cs | 3 - imBMW/Shields/ShieldBase.cs | 3 - imBMW/Shields/ShieldManager.cs | 4 +- imBMW/Shields/ShieldPort.cs | 3 - imBMW/Tools/ASCIIEncoding.cs | 3 - imBMW/Tools/ArrayHelpers.cs | 5 +- imBMW/Tools/DateTimeHelpers.cs | 1 - imBMW/Tools/EnumConverter.cs | 16 +- imBMW/Tools/ExtensionAttribute.cs | 4 +- imBMW/Tools/Logger.cs | 9 +- imBMW/Tools/Math.cs | 160 +++++ imBMW/Tools/NumHelpers.cs | 15 +- imBMW/Tools/Parse.cs | 190 ++++++ imBMW/Tools/QueueThreadWorker.cs | 41 +- imBMW/Tools/RCSwitch.cs | 576 ++++++++++++++++++ imBMW/Tools/StringBuilder.cs | 137 +++++ imBMW/Tools/StringHelpers.cs | 268 +++++++- imBMW/iBus/DeviceAddress.cs | 4 - .../iBus/Devices/Emulators/BordmonitorAUX.cs | 38 +- imBMW/iBus/Devices/Emulators/CDChanger.cs | 68 +-- imBMW/iBus/Devices/Emulators/MediaEmulator.cs | 21 +- imBMW/iBus/Devices/Real/BodyModule.cs | 68 ++- imBMW/iBus/Devices/Real/Bordmonitor.cs | 30 +- imBMW/iBus/Devices/Real/Immobiliser.cs | 2 - .../Real/InstrumentClusterElectronics.cs | 325 +++++++++- imBMW/iBus/Devices/Real/LightControlModule.cs | 2 - .../Real/MultiFunctionSteeringWheel.cs | 94 ++- imBMW/iBus/Devices/Real/Navigation.cs | 241 ++++++++ imBMW/iBus/Devices/Real/Radio.cs | 26 +- imBMW/iBus/Devices/Real/SeatMemory.cs | 125 ++++ imBMW/iBus/Diagnostics/DBusConverter.cs | 3 - imBMW/iBus/Diagnostics/DBusMessage.cs | 6 +- imBMW/iBus/Manager.cs | 100 ++- imBMW/iBus/Message.cs | 114 ++-- imBMW/iBus/MessageRegistry.cs | 552 +++++++++-------- imBMW/imBMW.csproj | 7 + 66 files changed, 3206 insertions(+), 1201 deletions(-) create mode 100644 imBMW/Features/Gates.cs create mode 100644 imBMW/Tools/Math.cs create mode 100644 imBMW/Tools/Parse.cs create mode 100644 imBMW/Tools/RCSwitch.cs create mode 100644 imBMW/Tools/StringBuilder.cs create mode 100644 imBMW/iBus/Devices/Real/Navigation.cs create mode 100644 imBMW/iBus/Devices/Real/SeatMemory.cs diff --git a/Devices/V2/Program.cs b/Devices/V2/Program.cs index f32c612..7a40027 100644 --- a/Devices/V2/Program.cs +++ b/Devices/V2/Program.cs @@ -1,4 +1,5 @@ using GHI.OSHW.Hardware; +using imBMW.Features; using imBMW.iBus; using imBMW.iBus.Devices.Real; using imBMW.Tools; @@ -10,10 +11,7 @@ using GHI.Hardware.FEZCerb; using imBMW.Multimedia; using System.Collections; -using System.Text; -using imBMW.Tools; using Microsoft.SPOT.IO; -using System.IO; using imBMW.Features.Menu; using imBMW.iBus.Devices.Emulators; using imBMW.Features.Menu.Screens; @@ -41,23 +39,6 @@ static void Init2() LED.Write(true); } - - - - - - - - - - - - - - - - - class Button { static ArrayList buttons = new ArrayList(); @@ -72,17 +53,17 @@ public static void OnPress(Cpu.Pin pin, Action callback) } } - static IAudioPlayer player; + static IAudioPlayer _player; static void Init() { LED = new OutputPort(Pin.PA8, false); - var version = "HW V2, FW V1.0"; + const string version = "HW V2, FW V1.0"; SettingsScreen.Instance.Status = version; Logger.Info(version); - var sd = GetRootDirectory(); + //var sd = GetRootDirectory(); // todo get config @@ -104,16 +85,16 @@ static void Init() }*/ // Enable iBus Manager - iBus.Manager.Init(iBusPort); + Manager.Init(iBusPort); Logger.Info("iBus manager inited"); Message sent1 = null, sent2 = null; // light "buffer" for last 2 messages bool isSent1 = false; - iBus.Manager.BeforeMessageReceived += (e) => + Manager.BeforeMessageReceived += (e) => { LED.Write(Busy(true, 1)); }; - iBus.Manager.AfterMessageReceived += (e) => + Manager.AfterMessageReceived += (e) => { LED.Write(Busy(false, 1)); #if DEBUG @@ -147,11 +128,11 @@ static void Init() //Logger.Info(e.Message.PacketDump); #endif }; - iBus.Manager.BeforeMessageSent += (e) => + Manager.BeforeMessageSent += e => { LED.Write(Busy(true, 2)); }; - iBus.Manager.AfterMessageSent += (e) => + Manager.AfterMessageSent += e => { LED.Write(Busy(false, 2)); #if DEBUG @@ -171,40 +152,45 @@ static void Init() // Enable comfort features //Features.Comfort.AllFeaturesEnabled = true; - Features.Comfort.AutoLockDoors = true; - Features.Comfort.AutoUnlockDoors = true; - Features.Comfort.AutoCloseWindows = true; + Comfort.AutoLockDoors = false; + Comfort.AutoUnlockDoors = true; + Comfort.AutoCloseWindows = true; Logger.Info("Comfort features inited"); + var rcSwitch = new RCSwitch(Pin.PC0); + Gates.Init(rcSwitch); + Gates.AddGatesObserver(54.708527777777782f, 25.289972222222225f, 0.1f, GateToggleMethod.Send433MhzSignal, new[] { "477D33", "477D3C" }); + // Set iPod or Bluetooth as AUX or CDC-emulator - player = new BluetoothOVC3860(Serial.COM2, sd != null ? sd + @"\contacts.vcf" : null); + _player = new BluetoothOVC3860(Serial.COM2); + //sd != null ? sd + @"\contacts.vcf" : null); //player = new iPodViaHeadset(Pin.PC2); Radio.Init(); Logger.Info("Radio inited"); - if (Manager.FindDevice(DeviceAddress.OnBoardMonitor)) + //if (Manager.FindDevice(DeviceAddress.OnBoardMonitor)) { MediaEmulator emulator; - emulator = new BordmonitorAUX(player); + emulator = new BordmonitorAUX(_player); //emulator = new CDChanger(player); //MenuScreen.MaxItemsCount = 6; //Bordmonitor.MK2Mode = true; BordmonitorMenu.Init(emulator); Logger.Info("BordmonitorAUX inited"); } - else - { - // TODO implement radio menu - //iBus.Devices.Emulators.CDChanger.Init(player); - Logger.Info("CDChanger emulator inited"); - } + //else + //{ + // // TODO implement radio menu + // //iBus.Devices.Emulators.CDChanger.Init(player); + // Logger.Info("CDChanger emulator inited"); + //} ShieldLED = new OutputPort(Pin.PA7, false); - player.IsPlayingChanged += (p, s) => + _player.IsPlayingChanged += (p, s) => { ShieldLED.Write(s); RefreshLEDs(); }; - player.StatusChanged += (p, s, e) => + _player.StatusChanged += (p, s, e) => { if (e == PlayerEvent.IncomingCall && !p.IsEnabled) { @@ -235,7 +221,7 @@ static void Init() static void RefreshLEDs() { byte b = 0; - if (error) + if (_error) { b = b.AddBit(0); } @@ -243,7 +229,7 @@ static void RefreshLEDs() { //b = b.AddBit(2); } - if (player.IsPlaying) + if (_player.IsPlaying) { b = b.AddBit(4); } @@ -255,7 +241,7 @@ public static string GetRootDirectory() try { Logger.Info("Mount", "SD"); - GHI.OSHW.Hardware.StorageDev.MountSD(); + StorageDev.MountSD(); Logger.Info("Mounted", "SD"); } catch @@ -281,10 +267,7 @@ public static string GetRootDirectory() Logger.Info(folders[i]);*/ return rootDirectory; } - else - { - Logger.Error("Card not formatted!", "SD"); - } + Logger.Error("Card not formatted!", "SD"); } catch (Exception ex) { @@ -296,20 +279,13 @@ public static string GetRootDirectory() static Timer blinkerTimer; static bool blinkerOn = true; - static byte busy = 0; - static bool error = false; + static byte _busy; + static bool _error; static bool Busy(bool busy, byte type) { - if (busy) - { - Program.busy = Program.busy.AddBit(type); - } - else - { - Program.busy = Program.busy.RemoveBit(type); - } - return Program.busy > 0; + _busy = busy ? _busy.AddBit(type) : _busy.RemoveBit(type); + return _busy > 0; } public static void Main() @@ -337,14 +313,13 @@ public static void Main() static void Logger_Logged(LoggerArgs args) { - if (args.Priority == Tools.LogPriority.Error) + if (args.Priority == LogPriority.Error) { // store errors to arraylist - error = true; + _error = true; RefreshLEDs(); } Debug.Print(args.LogString); } - } } diff --git a/imBMW/Features/Comfort.cs b/imBMW/Features/Comfort.cs index bc12f40..2f04d6a 100644 --- a/imBMW/Features/Comfort.cs +++ b/imBMW/Features/Comfort.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.iBus.Devices.Real; using System.Threading; using imBMW.Tools; @@ -12,62 +10,63 @@ public static class Comfort enum Command { FullCloseWindows, - FullOpenWindows + FullOpenWindows, + UnlockDoors } #endregion - static QueueThreadWorker commands; + static readonly QueueThreadWorker Commands; - static bool needLockDoors = true; - static bool needUnlockDoors = false; - static bool needComfortClose = true; + static bool _needLockDoors = true; + static bool _needUnlockDoors; + static bool _needComfortClose = true; static Comfort() { - commands = new QueueThreadWorker(ProcessCommand); + Commands = new QueueThreadWorker(ProcessCommand); - InstrumentClusterElectronics.SpeedRPMChanged += (e) => + InstrumentClusterElectronics.SpeedRPMChanged += e => { - if (needLockDoors && e.Speed > DoorsLockSpeed) + if (_needLockDoors && e.Speed > DoorsLockSpeed) { if (AutoLockDoors) { BodyModule.LockDoors(); } - needLockDoors = false; - needUnlockDoors = true; + _needLockDoors = false; + _needUnlockDoors = true; } if (e.Speed == 0) { - needLockDoors = true; + _needLockDoors = true; } }; - InstrumentClusterElectronics.IgnitionStateChanged += (e) => + InstrumentClusterElectronics.IgnitionStateChanged += e => { - if (!needComfortClose + if (!_needComfortClose && e.CurrentIgnitionState != IgnitionState.Off && e.PreviousIgnitionState == IgnitionState.Off) { - needComfortClose = true; + _needComfortClose = true; } - if (needUnlockDoors && e.CurrentIgnitionState == IgnitionState.Off) + if (_needUnlockDoors && e.CurrentIgnitionState == IgnitionState.Off) { if (AutoUnlockDoors) { - BodyModule.UnlockDoors(); + Commands.Enqueue(Command.UnlockDoors); } - needUnlockDoors = false; - needLockDoors = true; + _needUnlockDoors = false; + _needLockDoors = true; } }; - BodyModule.RemoteKeyButtonPressed += (e) => + BodyModule.RemoteKeyButtonPressed += e => { - if (e.Button == RemoteKeyButton.Lock && needComfortClose) + if (e.Button == RemoteKeyButton.Lock && _needComfortClose) { - needComfortClose = false; + _needComfortClose = false; if (AutoCloseWindows) { - commands.Enqueue(Command.FullCloseWindows); + Commands.Enqueue(Command.FullCloseWindows); } if (AutoCloseSunroof) { @@ -108,6 +107,11 @@ private static void ProcessCommand(object o) Thread.Sleep(3000); BodyModule.OpenWindows(); break; + case Command.UnlockDoors: + BodyModule.UnlockDoors(); + Thread.Sleep(1000); + BodyModule.UnlockDoors(); + break; } } @@ -154,11 +158,11 @@ public static bool NextComfortCloseEnabled { get { - return needComfortClose; + return _needComfortClose; } set { - needComfortClose = value; + _needComfortClose = value; } } @@ -169,12 +173,12 @@ public static bool AllFeaturesEnabled { set { - Features.Comfort.AutoLockDoors = value; - Features.Comfort.AutoUnlockDoors = value; - Features.Comfort.AutoCloseWindows = value; - Features.Comfort.AutoCloseSunroof = value; - Features.Comfort.AutoFoldMirrors = value; - Features.Comfort.AutoUnfoldMirrors = value; + AutoLockDoors = value; + AutoUnlockDoors = value; + AutoCloseWindows = value; + AutoCloseSunroof = value; + AutoFoldMirrors = value; + AutoUnfoldMirrors = value; } } } diff --git a/imBMW/Features/Gates.cs b/imBMW/Features/Gates.cs new file mode 100644 index 0000000..0e21d42 --- /dev/null +++ b/imBMW/Features/Gates.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections; +using System.Threading; +using imBMW.iBus.Devices.Real; +using imBMW.Tools; + +namespace imBMW.Features +{ + public static class Gates + { + #region Private types + + private class GatePoint + { + public float Latitude { get; private set; } + public float Longitude { get; private set; } + + public float MaxDistance { get; private set; } + + public GateToggleMethod ToggleMethod { get; private set; } + public object[] ToggleMethodArguments { get; private set; } + + public GatePoint(float latitude, float longitude, float distance, GateToggleMethod method, object[] methodArguments) + { + Latitude = latitude; + Longitude = longitude; + MaxDistance = distance; + ToggleMethod = method; + ToggleMethodArguments = methodArguments; + } + } + + #endregion + + #region Private static fields + + private static readonly QueueThreadWorker ThreadWorker = new QueueThreadWorker(ProcessItem); + + private static bool _initialized; + private static readonly object LockObject = new object(); + private static readonly ArrayList Objects = new ArrayList(); + + private static Thread _sendThread; + private static bool _exitSendThread; + + //private static Coordinate LastCoordinate; + private static Coordinate _currentCoordinate; + + private static RCSwitch _switch; + + #endregion + + #region Static constructor + + static Gates() + { + Navigation.CoordinatesChangedReceived += args => ThreadWorker.EnqueueArray(args.NewCoordinates); + } + + #endregion + + #region Private static methods + + private static bool NeedSend() + { + lock (LockObject) + { + foreach (GatePoint gatePoint in Objects) + { + var distance = _currentCoordinate.Distance(gatePoint.Latitude, gatePoint.Longitude); + if (distance < gatePoint.MaxDistance) + { + return true; + } + } + return false; + } + } + + private static void SendThread() + { + for (int i = 0; i < 10 && !_exitSendThread; i++) + { + lock (LockObject) + { + foreach (GatePoint gatePoint in Objects) + { + var distance = _currentCoordinate.Distance(gatePoint.Latitude, gatePoint.Longitude); + if (distance < gatePoint.MaxDistance) + { + Logger.Info("Sending signal to gates to open"); + switch (gatePoint.ToggleMethod) + { + case GateToggleMethod.Send433MhzSignal: + foreach (var arg in gatePoint.ToggleMethodArguments) + { + var code = Parse(arg.ToString()); + _switch.Send(code, 24); + } + break; + } + } + } + } + Thread.Sleep(10000); + } + } + + public static ulong Parse(string hex) + { + if (StringHelpers.IsNullOrEmpty(hex)) throw new ArgumentException("hex"); + + int i = hex.Length > 1 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X') ? 2 : 0; + ulong value = 0; + + while (i < hex.Length) + { + uint x = hex[i++]; + + if (x >= '0' && x <= '9') x = x - '0'; + else if (x >= 'A' && x <= 'F') x = (x - 'A') + 10; + else if (x >= 'a' && x <= 'f') x = (x - 'a') + 10; + else throw new ArgumentOutOfRangeException("hex"); + + value = 16 * value + x; + + } + + return value; + } + + private static void ProcessItem(object item) + { + var coordinates = item as Coordinate; + if (coordinates == null) return; + lock (LockObject) + { + if (!_initialized) return; + + //LastCoordinate = _currentCoordinate; + _currentCoordinate = coordinates; + + bool needSend = NeedSend(); + if (_sendThread != null && _sendThread.IsAlive) + { + // Check the last coordinate if there is a need to stop the thread + if (!needSend) + { + _exitSendThread = true; + _sendThread.Join(); + _sendThread = null; + } + return; + } + + if (needSend) + { + _sendThread = new Thread(SendThread) { Priority = ThreadPriority.Highest }; + _sendThread.Start(); + } + } + } + + #endregion + + #region Public static methods + + public static void Init(RCSwitch rcSwitch) + { + lock (LockObject) + { + if (_initialized) return; + _switch = rcSwitch; + _initialized = true; + } + } + + public static void AddGatesObserver(float latitude, float longitude, float distance, GateToggleMethod method, object[] methodArguments) + { + lock (LockObject) + { + if (!_initialized) throw new Exception("Gates are not initialized yet"); + if (methodArguments == null || methodArguments.Length == 0) throw new ApplicationException("Invalid or empty arguments specified"); + Objects.Add(new GatePoint(latitude, longitude, distance, method, methodArguments)); + } + } + + #endregion + } + + public enum GateToggleMethod + { + Send433MhzSignal, + } +} diff --git a/imBMW/Features/Light.cs b/imBMW/Features/Light.cs index cde421e..ae01733 100644 --- a/imBMW/Features/Light.cs +++ b/imBMW/Features/Light.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.iBus.Devices.Real; using imBMW.Tools; using imBMW.iBus; diff --git a/imBMW/Features/Localizations/EnglishLocalization.cs b/imBMW/Features/Localizations/EnglishLocalization.cs index 8462c23..5e7a713 100644 --- a/imBMW/Features/Localizations/EnglishLocalization.cs +++ b/imBMW/Features/Localizations/EnglishLocalization.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Features.Localizations { public class EnglishLocalization : Localization diff --git a/imBMW/Features/Localizations/Localization.cs b/imBMW/Features/Localizations/Localization.cs index ea3f0c5..22bce4f 100644 --- a/imBMW/Features/Localizations/Localization.cs +++ b/imBMW/Features/Localizations/Localization.cs @@ -1,23 +1,20 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Features.Localizations { public abstract class Localization { - protected static Localization current; + protected static Localization _current; public static Localization Current { get { - if (current == null) + if (_current == null) { - current = new EnglishLocalization(); + _current = new EnglishLocalization(); } - return Localization.current; + return _current; } - set { Localization.current = value; } + set { _current = value; } } #region Keys diff --git a/imBMW/Features/Localizations/RussianLocalization.cs b/imBMW/Features/Localizations/RussianLocalization.cs index e98f556..55713a3 100644 --- a/imBMW/Features/Localizations/RussianLocalization.cs +++ b/imBMW/Features/Localizations/RussianLocalization.cs @@ -1,7 +1,4 @@ -using System; -using Microsoft.SPOT; - -namespace imBMW.Features.Localizations +namespace imBMW.Features.Localizations { public class RussianLocalization : Localization { diff --git a/imBMW/Features/Menu/BordmonitorMenu.cs b/imBMW/Features/Menu/BordmonitorMenu.cs index 4afd445..8afc8d3 100644 --- a/imBMW/Features/Menu/BordmonitorMenu.cs +++ b/imBMW/Features/Menu/BordmonitorMenu.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using imBMW.iBus.Devices.Real; using imBMW.iBus; using imBMW.Tools; @@ -13,20 +12,20 @@ namespace imBMW.Features.Menu { public class BordmonitorMenu : MenuBase { - static BordmonitorMenu instance; + static BordmonitorMenu _instance; - MediaEmulator mediaEmulator; + readonly MediaEmulator _mediaEmulator; - bool skipRefreshScreen; - bool skipClearScreen; - bool skipClearTillRefresh; - bool disableRadioMenu; - bool isScreenSwitched; - object drawLock = new object(); + bool _skipRefreshScreen; + bool _skipClearScreen; + bool _skipClearTillRefresh; + bool _disableRadioMenu; + bool _isScreenSwitched; + readonly object _drawLock = new object(); private BordmonitorMenu(MediaEmulator mediaEmulator) { - this.mediaEmulator = mediaEmulator; + _mediaEmulator = mediaEmulator; mediaEmulator.IsEnabledChanged += mediaEmulator_IsEnabledChanged; mediaEmulator.PlayerIsPlayingChanged += ShowPlayerStatus; mediaEmulator.PlayerStatusChanged += ShowPlayerStatus; @@ -39,13 +38,13 @@ private BordmonitorMenu(MediaEmulator mediaEmulator) public static BordmonitorMenu Init(MediaEmulator mediaEmulator) { - if (instance != null) + if (_instance != null) { // TODO implement hot switch of emulators throw new Exception("Already inited"); } - instance = new BordmonitorMenu(mediaEmulator); - return instance; + _instance = new BordmonitorMenu(mediaEmulator); + return _instance; } #region Player items @@ -61,9 +60,9 @@ void ShowPlayerStatus(IAudioPlayer player, bool isPlaying) ShowPlayerStatus(player, s); } - Timer displayTextDelayTimer; - const int displayTextDelay = 2000; - const int statusTextMaxlen = 11; + Timer _displayTextDelayTimer; + const int DisplayTextDelay = 2000; + const int StatusTextMaxlen = 11; void ShowPlayerStatus(IAudioPlayer player, string status, PlayerEvent playerEvent) { @@ -105,14 +104,11 @@ string TextWithIcon(string icon, string text = null) { text = ""; } - if (icon.Length + text.Length < statusTextMaxlen) + if (icon.Length + text.Length < StatusTextMaxlen) { return icon + " " + text; } - else - { - return icon + text; - } + return icon + text; } void ShowPlayerStatus(IAudioPlayer player, string status) @@ -121,10 +117,10 @@ void ShowPlayerStatus(IAudioPlayer player, string status) { return; } - if (displayTextDelayTimer != null) + if (_displayTextDelayTimer != null) { - displayTextDelayTimer.Dispose(); - displayTextDelayTimer = null; + _displayTextDelayTimer.Dispose(); + _displayTextDelayTimer = null; } player.Menu.Status = status; @@ -132,16 +128,16 @@ void ShowPlayerStatus(IAudioPlayer player, string status) public void ShowPlayerStatusWithDelay(IAudioPlayer player) { - if (displayTextDelayTimer != null) + if (_displayTextDelayTimer != null) { - displayTextDelayTimer.Dispose(); - displayTextDelayTimer = null; + _displayTextDelayTimer.Dispose(); + _displayTextDelayTimer = null; } - displayTextDelayTimer = new Timer(delegate + _displayTextDelayTimer = new Timer(delegate { ShowPlayerStatus(player); - }, null, displayTextDelay, 0); + }, null, DisplayTextDelay, 0); } void mediaEmulator_PlayerChanged(IAudioPlayer player) @@ -166,7 +162,7 @@ protected override void ScreenWakeup() { base.ScreenWakeup(); - disableRadioMenu = true; + _disableRadioMenu = true; } public override void UpdateScreen() @@ -196,10 +192,10 @@ protected void ProcessRadioMessage(Message m) if (isRefresh) { m.ReceiverDescription = "Screen refresh"; - skipClearTillRefresh = false; - if (skipRefreshScreen) + _skipClearTillRefresh = false; + if (_skipRefreshScreen) { - skipRefreshScreen = false; + _skipRefreshScreen = false; return; } } @@ -207,9 +203,9 @@ protected void ProcessRadioMessage(Message m) if (isClear) { m.ReceiverDescription = "Screen clear"; - if (skipClearScreen || skipClearTillRefresh) + if (_skipClearScreen || _skipClearTillRefresh) { - skipClearScreen = false; + _skipClearScreen = false; return; } } @@ -220,9 +216,9 @@ protected void ProcessRadioMessage(Message m) IsScreenSwitched = false; } - if (disableRadioMenu || isClear) + if (_disableRadioMenu || isClear) { - disableRadioMenu = false; + _disableRadioMenu = false; Bordmonitor.DisableRadioMenu(); return; } @@ -244,7 +240,7 @@ protected void ProcessRadioMessage(Message m) break; case 0x02: m.ReceiverDescription = "Screen SW by rad"; - skipClearScreen = true; // to prevent on "clear screen" update on switch to BC/nav + _skipClearScreen = true; // to prevent on "clear screen" update on switch to BC/nav break; } IsScreenSwitched = true; @@ -258,10 +254,10 @@ protected void ProcessRadioMessage(Message m) return; }*/ - if (m.Data.StartsWith(Bordmonitor.DataShowTitle) && (lastTitle == null || !lastTitle.Data.Compare(m.Data))) + if (m.Data.StartsWith(Bordmonitor.DataShowTitle) && (_lastTitle == null || !_lastTitle.Data.Compare(m.Data))) { IsScreenSwitched = false; - disableRadioMenu = true; + _disableRadioMenu = true; UpdateScreen(); return; } @@ -322,35 +318,35 @@ protected void ProcessToRadioMessage(Message m) break; case 0x10: m.ReceiverDescription = "BM Button < prev track"; - mediaEmulator.Player.Prev(); + _mediaEmulator.Player.Prev(); break; case 0x00: m.ReceiverDescription = "BM Button > next track"; - mediaEmulator.Player.Next(); + _mediaEmulator.Player.Next(); break; } return; } } - bool isDrawing; - Message lastTitle; + bool _isDrawing; + Message _lastTitle; protected override void DrawScreen() { - if (isDrawing) + if (_isDrawing) { return; // TODO test } - lock (drawLock) + lock (_drawLock) { - isDrawing = true; - skipRefreshScreen = true; - skipClearTillRefresh = true; // TODO test no screen items lost + _isDrawing = true; + _skipRefreshScreen = true; + _skipClearTillRefresh = true; // TODO test no screen items lost base.DrawScreen(); Bordmonitor.ShowText(CurrentScreen.Status ?? String.Empty, BordmonitorFields.Status); - lastTitle = Bordmonitor.ShowText(CurrentScreen.Title ?? String.Empty, BordmonitorFields.Title); + _lastTitle = Bordmonitor.ShowText(CurrentScreen.Title ?? String.Empty, BordmonitorFields.Title); for (byte i = 0; i < 10; i++) { var index = GetItemIndex(i, true); @@ -358,10 +354,10 @@ protected override void DrawScreen() var s = item == null ? String.Empty : item.Text; Bordmonitor.ShowText(s ?? String.Empty, BordmonitorFields.Item, i, item != null && item.IsChecked); } - skipRefreshScreen = true; - skipClearTillRefresh = true; + _skipRefreshScreen = true; + _skipClearTillRefresh = true; Bordmonitor.RefreshScreen(); - isDrawing = false; + _isDrawing = false; } } @@ -386,14 +382,14 @@ byte GetItemIndex(byte index, bool back = false) public bool IsScreenSwitched { - get { return isScreenSwitched; } + get { return _isScreenSwitched; } set { - if (isScreenSwitched == value) + if (_isScreenSwitched == value) { return; } - isScreenSwitched = value; + _isScreenSwitched = value; if (value) { ScreenSuspend(); @@ -412,12 +408,12 @@ public static BordmonitorMenu Instance { get { - if (instance == null) + if (_instance == null) { //instance = new BordmonitorMenu(); throw new Exception("Not inited BM menu"); } - return instance; + return _instance; } } } diff --git a/imBMW/Features/Menu/MenuBase.cs b/imBMW/Features/Menu/MenuBase.cs index 4bb8367..08f72b9 100644 --- a/imBMW/Features/Menu/MenuBase.cs +++ b/imBMW/Features/Menu/MenuBase.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using System.Collections; using imBMW.Features.Menu.Screens; using imBMW.Tools; @@ -8,15 +6,16 @@ namespace imBMW.Features.Menu { public class MenuBase { - bool isEnabled; - MenuScreen homeScreen; - MenuScreen currentScreen; - Stack navigationStack = new Stack(); + bool _isEnabled; + + readonly MenuScreen _homeScreen; + MenuScreen _currentScreen; + readonly Stack _navigationStack = new Stack(); public MenuBase() { - homeScreen = HomeScreen.Instance; - CurrentScreen = homeScreen; + _homeScreen = HomeScreen.Instance; + CurrentScreen = _homeScreen; } protected virtual void DrawScreen() { } @@ -33,14 +32,14 @@ protected virtual void ScreenWakeup() public bool IsEnabled { - get { return isEnabled; } + get { return _isEnabled; } set { - if (isEnabled == value) + if (_isEnabled == value) { return; } - isEnabled = value; + _isEnabled = value; if (value) { ScreenWakeup(); @@ -73,15 +72,15 @@ public void Navigate(MenuScreen screen) { return; } - navigationStack.Push(CurrentScreen); + _navigationStack.Push(CurrentScreen); CurrentScreen = screen; } public void NavigateBack() { - if (navigationStack.Count > 0) + if (_navigationStack.Count > 0) { - CurrentScreen = navigationStack.Pop() as MenuScreen; + CurrentScreen = _navigationStack.Pop() as MenuScreen; } else { @@ -91,14 +90,14 @@ public void NavigateBack() public void NavigateHome() { - CurrentScreen = homeScreen; - navigationStack.Clear(); + CurrentScreen = _homeScreen; + _navigationStack.Clear(); } public void NavigateAfterHome(MenuScreen screen) { - navigationStack.Clear(); - navigationStack.Push(homeScreen); + _navigationStack.Clear(); + _navigationStack.Push(_homeScreen); CurrentScreen = screen; } @@ -106,17 +105,17 @@ public MenuScreen CurrentScreen { get { - return currentScreen; + return _currentScreen; } set { - if (currentScreen == value || value == null) + if (_currentScreen == value || value == null) { return; } - ScreenNavigatedFrom(currentScreen); - currentScreen = value; - ScreenNavigatedTo(currentScreen); + ScreenNavigatedFrom(_currentScreen); + _currentScreen = value; + ScreenNavigatedTo(_currentScreen); UpdateScreen(); } } diff --git a/imBMW/Features/Menu/MenuHelpers.cs b/imBMW/Features/Menu/MenuHelpers.cs index e4297c7..1c9f2fa 100644 --- a/imBMW/Features/Menu/MenuHelpers.cs +++ b/imBMW/Features/Menu/MenuHelpers.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Features.Localizations; namespace imBMW.Features.Menu diff --git a/imBMW/Features/Menu/MenuItem.cs b/imBMW/Features/Menu/MenuItem.cs index 84f0d58..5505b85 100644 --- a/imBMW/Features/Menu/MenuItem.cs +++ b/imBMW/Features/Menu/MenuItem.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; namespace imBMW.Features.Menu { @@ -25,10 +24,10 @@ public enum MenuItemType public class MenuItem { - private string text; - private bool isChecked; + private string _text; + private bool _isChecked; - private GetTextHandler getTextCallback; + private readonly GetTextHandler _getTextCallback; public MenuItem(string text, MenuItemType type = MenuItemType.Text, MenuItemAction action = MenuItemAction.None) { @@ -51,7 +50,7 @@ public MenuItem(string text, MenuItemEventHandler callback, MenuItemType type = public MenuItem(GetTextHandler getTextCallback, MenuItemType type = MenuItemType.Text, MenuItemAction action = MenuItemAction.None) : this(String.Empty, type, action) { - this.getTextCallback = getTextCallback; + _getTextCallback = getTextCallback; } public MenuItem(GetTextHandler getTextCallback, MenuItemEventHandler callback, MenuItemType type = MenuItemType.Button, MenuItemAction action = MenuItemAction.None) @@ -64,33 +63,33 @@ public string Text { get { - if (getTextCallback != null) + if (_getTextCallback != null) { - Text = getTextCallback(this); + Text = _getTextCallback(this); } - return text; + return _text; } set { - if (text == value) + if (_text == value) { return; } - text = value; + _text = value; Refresh(); } } public bool IsChecked { - get { return isChecked; } + get { return _isChecked; } set { - if (isChecked == value) + if (_isChecked == value) { return; } - isChecked = value; + _isChecked = value; OnCheckedChanged(); } } diff --git a/imBMW/Features/Menu/MenuScreen.cs b/imBMW/Features/Menu/MenuScreen.cs index f817c37..a683fd0 100644 --- a/imBMW/Features/Menu/MenuScreen.cs +++ b/imBMW/Features/Menu/MenuScreen.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using System.Collections; using imBMW.Tools; @@ -13,10 +12,10 @@ namespace imBMW.Features.Menu public class MenuScreen { - string title; - string status; - bool updateSuspended; - MenuBase parentMenu; + string _title; + string _status; + bool _updateSuspended; + MenuBase _parentMenu; public MenuScreen(string title = null) : this() @@ -53,17 +52,17 @@ public string Title { if (TitleCallback != null) { - title = TitleCallback(this); + _title = TitleCallback(this); } - return title; + return _title; } set { - if (title == value) + if (_title == value) { return; } - title = value; + _title = value; OnUpdated(); } } @@ -72,15 +71,15 @@ public string Status { get { - return status; + return _status; } set { - if (status == value) + if (_status == value) { return; } - status = value; + _status = value; OnUpdated(); } } @@ -148,15 +147,15 @@ public void ClearItems() public virtual bool OnNavigatedTo(MenuBase menu) { - if (parentMenu == menu) + if (_parentMenu == menu) { return false; } - if (parentMenu != null) + if (_parentMenu != null) { - throw new Exception("Already navigated to screen " + this + " in another menu " + parentMenu + ". Can't navigate in " + menu); + throw new Exception("Already navigated to screen " + this + " in another menu " + _parentMenu + ". Can't navigate in " + menu); } - parentMenu = menu; + _parentMenu = menu; var e = NavigatedTo; if (e != null) @@ -169,9 +168,9 @@ public virtual bool OnNavigatedTo(MenuBase menu) public virtual bool OnNavigatedFrom(MenuBase menu) { - if (parentMenu == menu) + if (_parentMenu == menu) { - parentMenu = null; + _parentMenu = null; var e = NavigatedFrom; if (e != null) @@ -181,9 +180,9 @@ public virtual bool OnNavigatedFrom(MenuBase menu) return true; } - if (parentMenu != null) + if (_parentMenu != null) { - throw new Exception("Navigated to screen " + this + " in another menu " + parentMenu + ". Can't navigate from in " + menu); + throw new Exception("Navigated to screen " + this + " in another menu " + _parentMenu + ". Can't navigate from in " + menu); } return false; } @@ -207,7 +206,7 @@ public bool IsNavigated { get { - return parentMenu != null; + return _parentMenu != null; } } @@ -218,15 +217,11 @@ public bool IsUpdateSuspended { get { - return updateSuspended; + return _updateSuspended; } set { - if (updateSuspended == value) - { - return; - } - updateSuspended = value; + _updateSuspended = value; } } @@ -260,7 +255,7 @@ protected void menuItem_Changed(MenuItem item) protected void OnUpdated() { - if (updateSuspended) + if (_updateSuspended) { return; } diff --git a/imBMW/Features/Menu/RadioMenu.cs b/imBMW/Features/Menu/RadioMenu.cs index c2a4821..34d6615 100644 --- a/imBMW/Features/Menu/RadioMenu.cs +++ b/imBMW/Features/Menu/RadioMenu.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Features.Menu { public class RadioMenu : MenuBase diff --git a/imBMW/Features/Menu/Screens/BordcomputerScreen.cs b/imBMW/Features/Menu/Screens/BordcomputerScreen.cs index 4ea3664..7848906 100644 --- a/imBMW/Features/Menu/Screens/BordcomputerScreen.cs +++ b/imBMW/Features/Menu/Screens/BordcomputerScreen.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using imBMW.iBus.Devices.Real; using imBMW.Tools; using imBMW.Features.Localizations; @@ -8,14 +7,14 @@ namespace imBMW.Features.Menu.Screens { public class BordcomputerScreen : MenuScreen { - protected static BordcomputerScreen instance; + protected static BordcomputerScreen _instance; - protected MenuItem itemPlayer; - protected MenuItem itemFav; - protected MenuItem itemBC; - protected MenuItem itemSettings; + protected MenuItem _itemPlayer; + protected MenuItem _itemFav; + protected MenuItem _itemBc; + protected MenuItem _itemSettings; - protected DateTime lastUpdated; + protected DateTime _lastUpdated; protected BordcomputerScreen() { @@ -42,11 +41,11 @@ protected bool UpdateItems() { //BodyModule.UpdateBatteryVoltage(); // TODO solve mem leak var now = DateTime.Now; - if (lastUpdated != DateTime.MinValue && (now - lastUpdated).GetTotalSeconds() < 4) + if (_lastUpdated != DateTime.MinValue && (now - _lastUpdated).GetTotalSeconds() < 4) { return false; } - lastUpdated = now; + _lastUpdated = now; OnUpdated(); return true; } @@ -78,14 +77,7 @@ protected void UpdateVoltage() public static BordcomputerScreen Instance { - get - { - if (instance == null) - { - instance = new BordcomputerScreen(); - } - return instance; - } + get { return _instance ?? (_instance = new BordcomputerScreen()); } } } } diff --git a/imBMW/Features/Menu/Screens/HomeScreen.cs b/imBMW/Features/Menu/Screens/HomeScreen.cs index 6870169..993fd8c 100644 --- a/imBMW/Features/Menu/Screens/HomeScreen.cs +++ b/imBMW/Features/Menu/Screens/HomeScreen.cs @@ -1,34 +1,32 @@ -using System; -using Microsoft.SPOT; using imBMW.Features.Localizations; namespace imBMW.Features.Menu.Screens { public class HomeScreen : MenuScreen { - protected static HomeScreen instance; + protected static HomeScreen _instance; - protected MenuItem itemPlayer; - protected MenuItem itemFav; - protected MenuItem itemBC; - protected MenuItem itemSettings; - protected MenuItem itemPhone; + protected MenuItem _itemPlayer; + protected MenuItem _itemFav; + protected MenuItem _itemBc; + protected MenuItem _itemSettings; + protected MenuItem _itemPhone; protected HomeScreen() { Title = "imBMW"; - itemPlayer = new MenuItem(i => Localization.Current.Player, MenuItemType.Button, MenuItemAction.GoToScreen); - itemPhone = new MenuItem(i => Localization.Current.Phone, MenuItemType.Button, MenuItemAction.GoToScreen); - itemFav = new MenuItem(i => Localization.Current.QuickAccess, MenuItemType.Button, MenuItemAction.GoToScreen) + _itemPlayer = new MenuItem(i => Localization.Current.Player, MenuItemType.Button, MenuItemAction.GoToScreen); + _itemPhone = new MenuItem(i => Localization.Current.Phone, MenuItemType.Button, MenuItemAction.GoToScreen); + _itemFav = new MenuItem(i => Localization.Current.QuickAccess, MenuItemType.Button, MenuItemAction.GoToScreen) { GoToScreen = null // TODO fav screen }; - itemBC = new MenuItem(i => Localization.Current.Bordcomputer, MenuItemType.Button, MenuItemAction.GoToScreen) + _itemBc = new MenuItem(i => Localization.Current.Bordcomputer, MenuItemType.Button, MenuItemAction.GoToScreen) { GoToScreen = BordcomputerScreen.Instance }; - itemSettings = new MenuItem(i => Localization.Current.Settings, MenuItemType.Button, MenuItemAction.GoToScreen) + _itemSettings = new MenuItem(i => Localization.Current.Settings, MenuItemType.Button, MenuItemAction.GoToScreen) { GoToScreen = SettingsScreen.Instance }; @@ -38,29 +36,29 @@ protected HomeScreen() protected virtual void SetItems() { ClearItems(); - if (itemPlayer.GoToScreen != null) + if (_itemPlayer.GoToScreen != null) { - AddItem(itemPlayer); + AddItem(_itemPlayer); } - if (itemPhone.GoToScreen != null) + if (_itemPhone.GoToScreen != null) { - AddItem(itemPhone); + AddItem(_itemPhone); } //AddItem(itemFav); - AddItem(itemBC); - AddItem(itemSettings); + AddItem(_itemBc); + AddItem(_itemSettings); } public MenuScreen PlayerScreen { get { - return itemPlayer.GoToScreen; + return _itemPlayer.GoToScreen; } set { // TODO check it is shown now and renavigate - itemPlayer.GoToScreen = value; + _itemPlayer.GoToScreen = value; SetItems(); } } @@ -69,25 +67,18 @@ public MenuScreen PhoneScreen { get { - return itemPhone.GoToScreen; + return _itemPhone.GoToScreen; } set { - itemPhone.GoToScreen = value; + _itemPhone.GoToScreen = value; SetItems(); } } public static HomeScreen Instance { - get - { - if (instance == null) - { - instance = new HomeScreen(); - } - return instance; - } + get { return _instance ?? (_instance = new HomeScreen()); } } } } diff --git a/imBMW/Features/Menu/Screens/SettingsScreen.cs b/imBMW/Features/Menu/Screens/SettingsScreen.cs index 2a9666b..b3277df 100644 --- a/imBMW/Features/Menu/Screens/SettingsScreen.cs +++ b/imBMW/Features/Menu/Screens/SettingsScreen.cs @@ -1,12 +1,10 @@ -using System; -using Microsoft.SPOT; using imBMW.Features.Localizations; namespace imBMW.Features.Menu.Screens { public class SettingsScreen : MenuScreen { - protected static SettingsScreen instance; + protected static SettingsScreen _instance; protected SettingsScreen() { @@ -52,14 +50,7 @@ void SwitchLanguage() public static SettingsScreen Instance { - get - { - if (instance == null) - { - instance = new SettingsScreen(); - } - return instance; - } + get { return _instance ?? (_instance = new SettingsScreen()); } } } } diff --git a/imBMW/IO/ISerialPort.cs b/imBMW/IO/ISerialPort.cs index d7c9bc9..21f3839 100644 --- a/imBMW/IO/ISerialPort.cs +++ b/imBMW/IO/ISerialPort.cs @@ -1,8 +1,3 @@ -using System; -using Microsoft.SPOT; -using System.IO.Ports; -using Microsoft.SPOT.Hardware; - namespace System.IO.Ports { public delegate void BusyChangedEventHandler(bool busy); diff --git a/imBMW/IO/SerialInterruptPort.cs b/imBMW/IO/SerialInterruptPort.cs index 17fb433..36869e5 100644 --- a/imBMW/IO/SerialInterruptPort.cs +++ b/imBMW/IO/SerialInterruptPort.cs @@ -1,8 +1,4 @@ -using System; -using System.Text; using System.Threading; -using System.Runtime.CompilerServices; -using Microsoft.SPOT; using Microsoft.SPOT.Hardware; namespace System.IO.Ports @@ -10,7 +6,7 @@ namespace System.IO.Ports /// /// Provides a connection to a serial communications port that supports line delimited reading and interruptable writing, including timeouts and DataReceived event implementation. /// - public class SerialInterruptPort : SerialInterruptPortBase, ISerialPort, IDisposable + public class SerialInterruptPort : SerialInterruptPortBase { /// /// The value of input pin when pauding the data output is requested. Default is true, that is, the input is of active high type. @@ -35,7 +31,7 @@ public SerialInterruptPort(SerialPortConfiguration config, Cpu.Pin busySignal, i else { // start monitoring the flow control pin for both edges _busy = new InterruptPort(busySignal, false, Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeBoth); - _busy.OnInterrupt += new NativeEventHandler(OnBusyChanged); + _busy.OnInterrupt += OnBusyChanged; } } @@ -69,4 +65,4 @@ protected override bool CanWrite } } } -} \ No newline at end of file +} diff --git a/imBMW/IO/SerialInterruptPortBase.cs b/imBMW/IO/SerialInterruptPortBase.cs index 22371ef..20b67e0 100644 --- a/imBMW/IO/SerialInterruptPortBase.cs +++ b/imBMW/IO/SerialInterruptPortBase.cs @@ -4,7 +4,7 @@ namespace System.IO.Ports { - public abstract class SerialInterruptPortBase : SerialPortBase, ISerialPort, IDisposable + public abstract class SerialInterruptPortBase : SerialPortBase, IDisposable { protected SerialPort _port; // The actual serial port we are wrapping. @@ -15,7 +15,7 @@ public abstract class SerialInterruptPortBase : SerialPortBase, ISerialPort, IDi /// The size of output buffer in bytes. Data output is paused for milliseconds every time this amount of data is sent. Can be zero to disable pausing. /// The size of input buffer in bytes. DataReceived event will fire only after this amount of data is received. Default is 1. /// Timeout of port reading. - public SerialInterruptPortBase(SerialPortConfiguration config, int writeBufferSize, int readBufferSize, int readTimeout = Timeout.Infinite) + protected SerialInterruptPortBase(SerialPortConfiguration config, int writeBufferSize, int readBufferSize, int readTimeout = Timeout.Infinite) : base(writeBufferSize, readBufferSize) { _port = new SerialPort(config.PortName, (int)config.BaudRate, config.Parity, config.DataBits, config.StopBits); // creating the serial port @@ -30,7 +30,7 @@ public SerialInterruptPortBase(SerialPortConfiguration config, int writeBufferSi /// Creates a new instance of SerialInterruptPort class, with hardware flow control and output pausing disabled. This corresponds to standard class behavior. /// /// An object that contains the configuration information for the serial port. - public SerialInterruptPortBase(SerialPortConfiguration config) : this(config, 0, 1) { } + protected SerialInterruptPortBase(SerialPortConfiguration config) : this(config, 0, 1) { } /// /// Releases resources used by a serial port. diff --git a/imBMW/IO/SerialPortBase.cs b/imBMW/IO/SerialPortBase.cs index ce82788..4baf6e7 100644 --- a/imBMW/IO/SerialPortBase.cs +++ b/imBMW/IO/SerialPortBase.cs @@ -1,9 +1,6 @@ -using System; -using Microsoft.SPOT; using System.Text; using System.Threading; using System.Runtime.CompilerServices; -using Microsoft.SPOT.Hardware; namespace System.IO.Ports { @@ -41,13 +38,13 @@ public abstract class SerialPortBase : ISerialPort protected AutoResetEvent _readToEvent; // Handles the thread synchronization when both DataReceived event is being requested and user calls ReadTo(). - public SerialPortBase() : this(0, 1) { } + protected SerialPortBase() : this(0, 1) { } - public SerialPortBase(int writeBufferSize, int readBufferSize) + protected SerialPortBase(int writeBufferSize, int readBufferSize) { // some initial parameter checks. if (writeBufferSize < 0) throw new ArgumentOutOfRangeException("writeBufferSize"); - if (readBufferSize < 1) throw new ArgumentOutOfRangeException("readBuferSize"); + if (readBufferSize < 1) throw new ArgumentOutOfRangeException("readBufferSize"); _writeBufferSize = writeBufferSize; _readBufferSize = readBufferSize; @@ -144,7 +141,6 @@ public void WriteLine(string text) #endregion - #region Reading protected abstract int ReadDirect(byte[] data, int offset, int length); @@ -172,7 +168,7 @@ public virtual byte[] ReadAvailable(int maxCount) { lock (_bufferSync) { - int count = System.Math.Min(_incomingBufferValidLength, maxCount); // update the count if there are less data available then requested + int count = Math.Min(_incomingBufferValidLength, maxCount); // update the count if there are less data available then requested byte[] data = GetBufferedData(count); // read the data from buffer AdvancePosition(count); // "remove" the data from buffer @@ -183,10 +179,10 @@ public virtual byte[] ReadAvailable(int maxCount) // The main loop of reading thread. This uses the blocking SerialPort.Read() method to monitor the serial port and fires the DataReceived event. protected void ReadLoop() { - byte[] buffer = new byte[_readBufferSize]; - int read; + var buffer = new byte[_readBufferSize]; while (_continueReading) { + int read; try { read = ReadDirect(buffer, 0, _readBufferSize); } // wait for some data (set _readBufferSize to 1 to wait for any data) catch (ThreadAbortException) { return; } // (if we were aborted, pass away silently) OnDataReceived(buffer, read); // and process it @@ -209,8 +205,7 @@ public virtual int Read(byte[] buffer, int offset, int count) AdvancePosition(usedLength); // and remove them. return usedLength; // TODO: Implement read timeout. } - else - return ReadDirect(buffer, offset, count); // Otherwise, we can directly read the serial port data. + return ReadDirect(buffer, offset, count); // Otherwise, we can directly read the serial port data. } /// @@ -283,12 +278,11 @@ protected virtual byte[] ReadTo(params byte[] mark) _readToEvent = null; // do some cleaning of stuff we don't need for the direct serial port manipulation if (timedOut) return null; - else - if (readToTimeout != null) - readToTimeout.Dispose(); + if (readToTimeout != null) + readToTimeout.Dispose(); } - byte[] data = new byte[System.Math.Max(_incomingBufferValidLength, _readBufferSize) + mark.Length]; + var data = new byte[Math.Max(_incomingBufferValidLength, _readBufferSize) + mark.Length]; int offset = GetBufferedData(data, 0, _incomingBufferValidLength); // read any data which left in the internal read buffer int markSearchStart = 0; @@ -296,7 +290,7 @@ protected virtual byte[] ReadTo(params byte[] mark) { if (offset >= data.Length) // If we have filled the buffer, make a bigger one! { // (the >= is for paranoia reasons, the offset never becomes greater than data.Length in this method) - byte[] biggerData = new byte[data.Length * 2]; + var biggerData = new byte[data.Length * 2]; data.CopyTo(biggerData, 0); data = biggerData; } @@ -319,7 +313,7 @@ protected virtual byte[] ReadTo(params byte[] mark) if (i >= mark.Length) { - byte[] finalData = new byte[markPos]; // if they do, copy data before marker into the new array + var finalData = new byte[markPos]; // if they do, copy data before marker into the new array Array.Copy(data, 0, finalData, 0, markPos); int remains = offset - markPos - mark.Length; @@ -336,8 +330,7 @@ protected virtual byte[] ReadTo(params byte[] mark) return finalData; } - else // If the other bytes do not match the mark bytes, it is not part of the mark, - markSearchStart = markPos + 1; // and start the next search at the next position. + markSearchStart = markPos + 1; // If the other bytes do not match the mark bytes, it is not part of the mark, and start the next search at the next position. } else markSearchStart = markPos; // We don't know if this is marker or not, so try again this position with more data. @@ -377,7 +370,6 @@ protected virtual int BufferIndexOf(byte[] what) #endregion - #region DataReceived event stuff protected object _bufferSync; // Sync root object for manipulation with the _incomingBuffer and/or its position/valid length fields. @@ -446,7 +438,7 @@ protected virtual void OnDataReceived(byte[] data, int validLength) /// An array of size arraySize, filled with data from internal read buffer, if available. protected byte[] GetBufferedData(int arraySize) { - byte[] data = new byte[arraySize]; // This method can be (and is) used to increase the internal buffer size, + var data = new byte[arraySize]; // This method can be (and is) used to increase the internal buffer size, GetBufferedData(data, 0, arraySize); // with the side effect of aligning the circular wrapped data linearly from the beginning. return data; } @@ -467,7 +459,7 @@ protected virtual int GetBufferedData(byte[] buffer, int offset, int count) // copy 1st phase: start1 = 9, end1 = 13 // copy 2nd phase: (start2 = 0) len2 = 2 (virtual copy end = 15) - count = System.Math.Min(_incomingBufferValidLength, count); + count = Math.Min(_incomingBufferValidLength, count); if (count < 1) return 0; int end1 = _incomingBufferPosition + count; // virtual copy end @@ -512,7 +504,7 @@ public virtual event SerialDataReceivedEventHandler DataReceived add { SerialDataReceivedEventHandler oldHandlers = _dataReceivedHandlers; - SerialDataReceivedEventHandler newHandlers = (SerialDataReceivedEventHandler)Delegate.Combine(oldHandlers, value); // add a new handler + var newHandlers = (SerialDataReceivedEventHandler)Delegate.Combine(oldHandlers, value); // add a new handler try { _dataReceivedHandlers = newHandlers; @@ -532,7 +524,7 @@ public virtual event SerialDataReceivedEventHandler DataReceived remove { SerialDataReceivedEventHandler oldHandlers = _dataReceivedHandlers; - SerialDataReceivedEventHandler newHandlers = (SerialDataReceivedEventHandler)Delegate.Remove(oldHandlers, value); // remove a handler + var newHandlers = (SerialDataReceivedEventHandler)Delegate.Remove(oldHandlers, value); // remove a handler try { _dataReceivedHandlers = newHandlers; diff --git a/imBMW/IO/SerialPortConfiguration.cs b/imBMW/IO/SerialPortConfiguration.cs index fb56ee9..ac9bc6a 100644 --- a/imBMW/IO/SerialPortConfiguration.cs +++ b/imBMW/IO/SerialPortConfiguration.cs @@ -1,23 +1,14 @@ -using System; -using Microsoft.SPOT; - namespace System.IO.Ports { public class SerialPortConfiguration { - string portName; - BaudRate baudRate; - Parity parity; - int dataBits; - StopBits stopBits; - public SerialPortConfiguration(string portName, BaudRate baudRate, Parity parity, int dataBits, StopBits stopBits) { - this.portName = portName; - this.baudRate = baudRate; - this.parity = parity; - this.dataBits = dataBits; - this.stopBits = stopBits; + PortName = portName; + BaudRate = baudRate; + Parity = parity; + DataBits = dataBits; + StopBits = stopBits; } public SerialPortConfiguration(string portName, BaudRate baudRate, Parity parity, int dataBits) : this(portName, baudRate, parity, dataBits, StopBits.One) { } @@ -26,34 +17,14 @@ public SerialPortConfiguration(string portName, BaudRate baudRate, Parity parity public SerialPortConfiguration(string portName, BaudRate baudRate) : this(portName, baudRate, Parity.None) { } - public StopBits StopBits - { - get { return stopBits; } - set { stopBits = value; } - } + public StopBits StopBits { get; set; } - public int DataBits - { - get { return dataBits; } - set { dataBits = value; } - } + public int DataBits { get; set; } - public Parity Parity - { - get { return parity; } - set { parity = value; } - } + public Parity Parity { get; set; } - public BaudRate BaudRate - { - get { return baudRate; } - set { baudRate = value; } - } + public BaudRate BaudRate { get; set; } - public string PortName - { - get { return portName; } - set { portName = value; } - } + public string PortName { get; set; } } } diff --git a/imBMW/IO/SerialPortHub.cs b/imBMW/IO/SerialPortHub.cs index 2a07093..da4f7f8 100644 --- a/imBMW/IO/SerialPortHub.cs +++ b/imBMW/IO/SerialPortHub.cs @@ -1,30 +1,26 @@ -using System; -using Microsoft.SPOT; -using System.Collections; -using System.Threading; using imBMW.Tools; namespace System.IO.Ports { - public class SerialPortHub : SerialPortBase, ISerialPort + public class SerialPortHub : SerialPortBase { - ISerialPort[] ports; - QueueThreadWorker[] queues; + readonly ISerialPort[] _ports; + readonly QueueThreadWorker[] _queues; public SerialPortHub(params ISerialPort[] ports) { - this.ports = ports; + _ports = ports; - queues = new QueueThreadWorker[ports.Length]; + _queues = new QueueThreadWorker[ports.Length]; for (int i = 0; i < ports.Length; i++) { int index = i; ISerialPort port = ports[index]; - queues[index] = new QueueThreadWorker((o) => + _queues[index] = new QueueThreadWorker(o => { - byte[] data = (byte[])o; + var data = (byte[])o; port.Write(data, 0, data.Length); }); } @@ -51,11 +47,11 @@ public override void Write(byte[] data, int offset, int length) protected void Write(byte[] data, int offset, int length, int except) { - if (except < 0 || except >= ports.Length) + if (except < 0 || except >= _ports.Length) { except = -1; } - int count = ports.Length - (except == -1 ? 0 : 1); + int count = _ports.Length - (except == -1 ? 0 : 1); if (count == 0) { return; @@ -66,11 +62,11 @@ protected void Write(byte[] data, int offset, int length, int except) data = data.SkipAndTake(offset, length); } - for (int i = 0; i < ports.Length; i++) + for (int i = 0; i < _ports.Length; i++) { if (i != except) { - queues[i].Enqueue(data); + _queues[i].Enqueue(data); } } } @@ -123,7 +119,7 @@ protected void Write(byte[] data, int offset, int length, int except) public override void Flush() { - foreach (ISerialPort port in ports) + foreach (ISerialPort port in _ports) { port.Flush(); } diff --git a/imBMW/IO/SerialPortOptoPair.cs b/imBMW/IO/SerialPortOptoPair.cs index ddf88b1..d12c0bf 100644 --- a/imBMW/IO/SerialPortOptoPair.cs +++ b/imBMW/IO/SerialPortOptoPair.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using System.Threading; namespace System.IO.Ports diff --git a/imBMW/IO/SerialPortTH3122.cs b/imBMW/IO/SerialPortTH3122.cs index 0f719ac..a1a393c 100644 --- a/imBMW/IO/SerialPortTH3122.cs +++ b/imBMW/IO/SerialPortTH3122.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using Microsoft.SPOT.Hardware; namespace System.IO.Ports diff --git a/imBMW/IO/SerialTimerInterruptPort.cs b/imBMW/IO/SerialTimerInterruptPort.cs index 743b091..38b7383 100644 --- a/imBMW/IO/SerialTimerInterruptPort.cs +++ b/imBMW/IO/SerialTimerInterruptPort.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Tools; using System.Threading; @@ -20,9 +18,8 @@ public class SerialTimerInterruptPort : SerialInterruptPortBase, ISerialPort, ID /// public bool IsWriteEchoed = false; - DateTime LastRead = DateTime.Now; - - Timer resumeTimer; + DateTime _lastRead = DateTime.Now; + Timer _resumeTimer; /// /// Creates a new instance of SerialInterruptPort class, allowing to specify buffer sizes and blocking input port. @@ -58,7 +55,7 @@ void OnBusyChanged() if (busy) { DisposeResumeTimer(); - resumeTimer = new Timer((s) => + _resumeTimer = new Timer((s) => { OnBusyChanged(false); DisposeResumeTimer(); @@ -68,10 +65,10 @@ void OnBusyChanged() void DisposeResumeTimer() { - if (resumeTimer != null) + if (_resumeTimer != null) { - resumeTimer.Dispose(); - resumeTimer = null; + _resumeTimer.Dispose(); + _resumeTimer = null; } } @@ -79,7 +76,7 @@ protected override bool CanWrite { get { - return (DateTime.Now - LastRead).GetTotalMilliseconds() >= AfterReadDelay; + return (DateTime.Now - _lastRead).GetTotalMilliseconds() >= AfterReadDelay; } } @@ -88,7 +85,7 @@ protected override int ReadDirect(byte[] data, int offset, int length) int res = base.ReadDirect(data, offset, length); if (res > 0 && (!IsWriteEchoed || _writeThread == null)) { - LastRead = DateTime.Now; + _lastRead = DateTime.Now; OnBusyChanged(); } return res; diff --git a/imBMW/Multimedia/AudioPlayerBase.cs b/imBMW/Multimedia/AudioPlayerBase.cs index 5cd364f..dcfc72a 100644 --- a/imBMW/Multimedia/AudioPlayerBase.cs +++ b/imBMW/Multimedia/AudioPlayerBase.cs @@ -1,16 +1,15 @@ using System; -using Microsoft.SPOT; -using imBMW.iBus.Devices.Real; using imBMW.Features.Menu; namespace imBMW.Multimedia { public abstract class AudioPlayerBase : IAudioPlayer { - bool isCurrentPlayer; - PlayerHostState playerHostState; - bool isEnabled; - protected bool isPlaying; + bool _isCurrentPlayer; + PlayerHostState _playerHostState; + bool _isEnabled; + + protected bool _isPlaying; public virtual void Play() { @@ -62,15 +61,15 @@ public bool IsEnabled { get { - return isEnabled; + return _isEnabled; } private set { - if (isEnabled == value) + if (_isEnabled == value) { return; } - isEnabled = value; + _isEnabled = value; OnIsEnabledChanged(value); } } @@ -79,15 +78,15 @@ public PlayerHostState PlayerHostState { get { - return playerHostState; + return _playerHostState; } set { - if (playerHostState == value) + if (_playerHostState == value) { return; } - playerHostState = value; + _playerHostState = value; OnPlayerHostStateChanged(value); } } @@ -96,15 +95,15 @@ public bool IsCurrentPlayer { get { - return isCurrentPlayer; + return _isCurrentPlayer; } set { - if (isCurrentPlayer == value) + if (_isCurrentPlayer == value) { return; } - isCurrentPlayer = value; + _isCurrentPlayer = value; OnIsCurrentPlayerChanged(value); } } @@ -120,7 +119,7 @@ protected virtual void OnIsCurrentPlayerChanged(bool isCurrentPlayer) { Pause(); } - else if (PlayerHostState == Multimedia.PlayerHostState.On) + else if (PlayerHostState == PlayerHostState.On) { Play(); } @@ -133,7 +132,7 @@ protected virtual void OnPlayerHostStateChanged(PlayerHostState playerHostState) void CheckIsEnabled() { - IsEnabled = PlayerHostState == Multimedia.PlayerHostState.On && IsCurrentPlayer; + IsEnabled = PlayerHostState == PlayerHostState.On && IsCurrentPlayer; } public event IsPlayingHandler IsPlayingChanged; diff --git a/imBMW/Multimedia/BluetoothOVC3860.cs b/imBMW/Multimedia/BluetoothOVC3860.cs index 8db1525..757ebaf 100644 --- a/imBMW/Multimedia/BluetoothOVC3860.cs +++ b/imBMW/Multimedia/BluetoothOVC3860.cs @@ -52,7 +52,7 @@ public void AddPhone(string phone) return; // TODO more than one phone } var phoneClear = ""; - foreach (var c in phone) + foreach (var c in phone.ToCharArray()) { if (c.IsNumeric() || c == '+') { @@ -71,10 +71,15 @@ public void AddPhone(string phone) /// public class BluetoothOVC3860 : AudioPlayerBase { - SerialPortBase port; - QueueThreadWorker queue; - MenuScreen menu; - string contactsPath; + readonly SerialPortBase _port; + readonly QueueThreadWorker _queue; + readonly string _contactsPath; + + MenuScreen _menu; + + int _contactsPerPage = 7; + int _offset; + MenuScreen _contactsScreen; /// /// @@ -84,16 +89,16 @@ public BluetoothOVC3860(string port, string contactsPath = null) { Name = "Bluetooth"; - queue = new QueueThreadWorker(ProcessSendCommand); + _queue = new QueueThreadWorker(ProcessSendCommand); - this.port = new SerialInterruptPort(new SerialPortConfiguration(port, BaudRate.Baudrate115200), Cpu.Pin.GPIO_NONE, 0, 16, 10); - this.port.DataReceived += port_DataReceived; + _port = new SerialInterruptPort(new SerialPortConfiguration(port, BaudRate.Baudrate115200), Cpu.Pin.GPIO_NONE, 0, 16, 10); + _port.DataReceived += port_DataReceived; if (contactsPath != null) { if (File.Exists(contactsPath)) { - this.contactsPath = contactsPath; + _contactsPath = contactsPath; } else { @@ -115,19 +120,19 @@ public ArrayList GetContacts(uint offset, uint count) var contacts = new ArrayList(); try { - if (contactsPath == null || !File.Exists(contactsPath)) + if (_contactsPath == null || !File.Exists(_contactsPath)) { Logger.Info("No contacts file"); return contacts; } - var handle = new FileStream(contactsPath, FileMode.Open, FileAccess.Read); + var handle = new FileStream(_contactsPath, FileMode.Open, FileAccess.Read); var data = new byte[1000]; - int read = 0; + int read; uint found = 0; bool skip = true; bool parse = false; - PhoneContact contact = new PhoneContact(); + var contact = new PhoneContact(); for (int i = 0; i < handle.Length; i += read) { handle.Seek(i, SeekOrigin.Begin); @@ -221,52 +226,49 @@ protected MenuScreen CreatePhoneScreen() return screen; } - int contactsPerPage = 7; - int offset = 0; - MenuScreen contactsScreen; - protected MenuScreen CreateContactsScreen() { - contactsPerPage = MenuScreen.MaxItemsCount - 3; + _contactsPerPage = MenuScreen.MaxItemsCount - 3; - contactsScreen = new MenuScreen(s => Localization.Current.Contacts); - contactsScreen.AddItem(new MenuItem(i => "< " + Localization.Current.PrevItems, i => { offset -= contactsPerPage; SetContactsScreenItems(); }), 0); // TODO navigate - contactsScreen.AddItem(new MenuItem(i => Localization.Current.NextItems + " >", i => { offset += contactsPerPage; SetContactsScreenItems(); }), 1); // TODO test, fix and make 1 - contactsScreen.AddBackButton(MenuScreen.MaxItemsCount - 1); + _contactsScreen = new MenuScreen(s => Localization.Current.Contacts); + _contactsScreen.AddItem(new MenuItem(i => "< " + Localization.Current.PrevItems, i => { _offset -= _contactsPerPage; SetContactsScreenItems(); }), 0); // TODO navigate + _contactsScreen.AddItem(new MenuItem(i => Localization.Current.NextItems + " >", i => { _offset += _contactsPerPage; SetContactsScreenItems(); }), 1); // TODO test, fix and make 1 + _contactsScreen.AddBackButton(MenuScreen.MaxItemsCount - 1); - contactsScreen.NavigatedTo += s => + _contactsScreen.NavigatedTo += s => { - offset = 0; // TODO don't scroll on navigate back + _offset = 0; // TODO don't scroll on navigate back SetContactsScreenItems(); }; - return contactsScreen; + return _contactsScreen; } protected void SetContactsScreenItems() { - if (offset < 0) + if (_offset < 0) { - offset = 0; + _offset = 0; } - var contacts = GetContacts((uint)offset, (uint)contactsPerPage); - if (contacts.Count == 0 && offset > 0) + var contacts = GetContacts((uint)_offset, (uint)_contactsPerPage); + if (contacts.Count == 0 && _offset > 0) { - offset = 0; + _offset = 0; SetContactsScreenItems(); return; } - contactsScreen.Status = Localization.Current.Refreshing; - contactsScreen.IsUpdateSuspended = true; + _contactsScreen.Status = Localization.Current.Refreshing; + _contactsScreen.IsUpdateSuspended = true; var i = 2; foreach (var c in contacts) { var contact = c as PhoneContact; - contactsScreen.AddItem(new MenuItem(contact.Name, it => CallPhone(contact.Phones)), i++); // TODO show phones + if (contact == null) continue; + _contactsScreen.AddItem(new MenuItem(contact.Name, it => CallPhone(contact.Phones)), i++); // TODO show phones } - contactsScreen.IsUpdateSuspended = false; - contactsScreen.Status = ""; + _contactsScreen.IsUpdateSuspended = false; + _contactsScreen.Status = ""; } protected override void SetPlaying(bool value) @@ -327,12 +329,12 @@ public override bool RandomToggle() return false; } - public override void VolumeUp() + public sealed override void VolumeUp() { SendCommand(CmdVolumeUp); } - public override void VolumeDown() + public sealed override void VolumeDown() { SendCommand(CmdVolumeDown); } @@ -341,15 +343,15 @@ public override bool IsPlaying { get { - return isPlaying; + return _isPlaying; } protected set { - if (isPlaying == value) + if (_isPlaying == value) { return; } - isPlaying = value; + _isPlaying = value; OnIsPlayingChanged(value); Logger.Info(value ? "Playing" : "Paused", "BT"); } @@ -359,18 +361,17 @@ public override MenuScreen Menu { get { - if (menu == null) + if (_menu == null) { - menu = new MenuScreen(Name); + _menu = new MenuScreen(Name); - var playerSettings = new MenuScreen(s => Localization.Current.Settings); - playerSettings.Status = Name; + var playerSettings = new MenuScreen(s => Localization.Current.Settings) {Status = Name}; playerSettings.AddItem(new MenuItem(i => Localization.Current.Volume + " +", i => VolumeUp())); playerSettings.AddItem(new MenuItem(i => Localization.Current.Volume + " -", i => VolumeDown())); playerSettings.AddItem(new MenuItem(i => Localization.Current.Reconnect, i => Reconnect()), 3); playerSettings.AddItem(new MenuItem(i => Localization.Current.Pair, i => { - if (lastCommand == "CA") + if (_lastCommand == "CA") { SendCommand("CB"); // cancel pair } @@ -381,14 +382,14 @@ public override MenuScreen Menu })); playerSettings.AddBackButton(); - menu.AddItem(new MenuItem(i => IsPlaying ? Localization.Current.Pause : Localization.Current.Play, i => PlayPauseToggle())); - menu.AddItem(new MenuItem(i => Localization.Current.NextTrack, i => Next())); - menu.AddItem(new MenuItem(i => Localization.Current.PrevTrack, i => Prev())); - menu.AddItem(new MenuItem(i => Localization.Current.Settings, MenuItemType.Button, MenuItemAction.GoToScreen) { GoToScreen = playerSettings }); - menu.AddBackButton(); - menu.Updated += m => playerSettings.Status = m.Status; + _menu.AddItem(new MenuItem(i => IsPlaying ? Localization.Current.Pause : Localization.Current.Play, i => PlayPauseToggle())); + _menu.AddItem(new MenuItem(i => Localization.Current.NextTrack, i => Next())); + _menu.AddItem(new MenuItem(i => Localization.Current.PrevTrack, i => Prev())); + _menu.AddItem(new MenuItem(i => Localization.Current.Settings, MenuItemType.Button, MenuItemAction.GoToScreen) { GoToScreen = playerSettings }); + _menu.AddBackButton(); + _menu.Updated += m => playerSettings.Status = m.Status; } - return menu; + return _menu; } } @@ -399,7 +400,7 @@ protected override void OnPlayerHostStateChanged(PlayerHostState playerHostState switch (playerHostState) { case PlayerHostState.On: - if (!connected) + if (!_connected) { Reconnect(); } @@ -430,12 +431,12 @@ protected override void OnPlayerHostStateChanged(PlayerHostState playerHostState const string CmdAnswer = "CE"; const string CmdCall = "CW"; - string lastCommand; - bool connected; + string _lastCommand; + bool _connected; public void Reconnect() { - if (connected) + if (_connected) { //SendCommand(CmdStop); //SendCommand("CD"); // disconn hfp @@ -462,40 +463,40 @@ void SendCommand(string command, string param = null) { command += param; } - lastCommand = command; - queue.Enqueue("AT#" + command); + _lastCommand = command; + _queue.Enqueue("AT#" + command); } void ProcessSendCommand(object o) { var s = (string)o; - port.WriteLine(s); + _port.WriteLine(s); Logger.Info(s, "BT>"); } - string btBuffer = ""; + string _btBuffer = ""; void port_DataReceived(object sender, SerialDataReceivedEventArgs e) { - if (port.AvailableBytes == 0) + if (_port.AvailableBytes == 0) { return; } - var data = port.ReadAvailable(); + var data = _port.ReadAvailable(); var s = ASCIIEncoding.GetString(data); - foreach (var c in s) + foreach (var c in s.ToCharArray()) { if (c == '\r' || c == '\n') { - if (btBuffer != "") + if (_btBuffer != "") { - ProcessBTNotification(btBuffer); + ProcessBTNotification(_btBuffer); } - btBuffer = ""; + _btBuffer = ""; } else { - btBuffer += c; + _btBuffer += c; } } } @@ -512,12 +513,12 @@ void ProcessBTNotification(string s) break; case "MG1": Logger.Info("HFP waiting", "BT"); - connected = false; + _connected = false; SendCommand("CC"); // conn hfp break; case "MG3": Logger.Info("HFP connected", "BT"); - connected = true; + _connected = true; SendCommand("MI"); // conn av break; case "MF01": @@ -526,13 +527,13 @@ void ProcessBTNotification(string s) break; case "MY": Logger.Info("AV disconnected", "BT"); - if (lastCommand == "MJ") + if (_lastCommand == "MJ") { SendCommand("CD"); // disconn hfp } break; case "MR": - if (!IsEnabled && lastCommand != CmdStop) + if (!IsEnabled && _lastCommand != CmdStop) { SendCommand(CmdStop); } @@ -564,7 +565,7 @@ void ProcessBTNotification(string s) Logger.Info("Previous", "BT"); break; case "IV": - connected = true; + _connected = true; Logger.Info("Connected", "BT"); OnStatusChanged(Localization.Current.Connected, PlayerEvent.Wireless); SendCommand("MI"); // conn av @@ -577,23 +578,23 @@ void ProcessBTNotification(string s) } break; case "II": - connected = false; + _connected = false; IsPlaying = false; Logger.Info("Waiting", "BT"); OnStatusChanged(Localization.Current.Waiting, PlayerEvent.Wireless); break; case "IA": - connected = false; + _connected = false; IsPlaying = false; Logger.Info("Disconnected", "BT"); OnStatusChanged(Localization.Current.Disconnected, PlayerEvent.Wireless); - if (lastCommand == "CD") + if (_lastCommand == "CD") { Reconnect(); } break; case "IJ2": - connected = false; + _connected = false; IsPlaying = false; Logger.Info("Cancel pairing", "BT"); OnStatusChanged(Localization.Current.NotPaired, PlayerEvent.Wireless); @@ -614,7 +615,7 @@ void ProcessBTNotification(string s) void ProcessBTOK() { - switch (lastCommand) + switch (_lastCommand) { case "CC": SendCommand("CY"); // query hfp status diff --git a/imBMW/Multimedia/IAudioPlayer.cs b/imBMW/Multimedia/IAudioPlayer.cs index d9c1204..54a23c2 100644 --- a/imBMW/Multimedia/IAudioPlayer.cs +++ b/imBMW/Multimedia/IAudioPlayer.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Features.Menu; namespace imBMW.Multimedia diff --git a/imBMW/Multimedia/MultiplexorTDA7313.cs b/imBMW/Multimedia/MultiplexorTDA7313.cs index 27fefb9..13ccad6 100644 --- a/imBMW/Multimedia/MultiplexorTDA7313.cs +++ b/imBMW/Multimedia/MultiplexorTDA7313.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Multimedia { public class MultiplexorTDA7313 diff --git a/imBMW/Multimedia/iPodViaHeadset.cs b/imBMW/Multimedia/iPodViaHeadset.cs index c683166..daab072 100644 --- a/imBMW/Multimedia/iPodViaHeadset.cs +++ b/imBMW/Multimedia/iPodViaHeadset.cs @@ -1,7 +1,5 @@ using imBMW.Features.Menu; -using imBMW.iBus.Devices.Real; using imBMW.Tools; -using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using System; using System.Threading; @@ -25,36 +23,36 @@ public enum iPodCommand const int VoiceOverMenuTimeoutSeconds = 60; - OutputPort iPod; - OutputPort iPodVolumeUp; - OutputPort iPodVolumeDown; - QueueThreadWorker iPodCommands; + readonly OutputPort _iPod; + readonly OutputPort _iPodVolumeUp; + readonly OutputPort _iPodVolumeDown; + readonly QueueThreadWorker _iPodCommands; - bool canControlVolume; - bool isInVoiceOverMenu; - DateTime voiceOverMenuStarted; + readonly bool _canControlVolume; + bool _isInVoiceOverMenu; + DateTime _voiceOverMenuStarted; public iPodViaHeadset(Cpu.Pin headsetControl, Cpu.Pin volumeUp = Cpu.Pin.GPIO_NONE, Cpu.Pin volumeDown = Cpu.Pin.GPIO_NONE) { Name = "iPod"; - iPod = new OutputPort(headsetControl, false); - canControlVolume = volumeUp != Cpu.Pin.GPIO_NONE && volumeDown != Cpu.Pin.GPIO_NONE; - if (canControlVolume) + _iPod = new OutputPort(headsetControl, false); + _canControlVolume = volumeUp != Cpu.Pin.GPIO_NONE && volumeDown != Cpu.Pin.GPIO_NONE; + if (_canControlVolume) { - iPodVolumeUp = new OutputPort(volumeUp, false); - iPodVolumeDown = new OutputPort(volumeDown, false); + _iPodVolumeUp = new OutputPort(volumeUp, false); + _iPodVolumeDown = new OutputPort(volumeDown, false); } - iPodCommands = new QueueThreadWorker(ExecuteIPodCommand); + _iPodCommands = new QueueThreadWorker(ExecuteIPodCommand); } void DisposePorts() { - iPod.Dispose(); - if (canControlVolume) + _iPod.Dispose(); + if (_canControlVolume) { - iPodVolumeUp.Dispose(); - iPodVolumeDown.Dispose(); + _iPodVolumeUp.Dispose(); + _iPodVolumeDown.Dispose(); } } @@ -73,9 +71,9 @@ public void Dispose() void PressIPodButton(bool longPause = false, int milliseconds = 50) { - iPod.Write(true); + _iPod.Write(true); Thread.Sleep(milliseconds); - iPod.Write(false); + _iPod.Write(false); Thread.Sleep(longPause ? 300 : 25); // Let iPod understand the command } @@ -135,16 +133,16 @@ void ExecuteIPodCommand(object c) break; case iPodCommand.VolumeUp: - iPodVolumeUp.Write(true); + _iPodVolumeUp.Write(true); Thread.Sleep(50); - iPodVolumeUp.Write(false); + _iPodVolumeUp.Write(false); Thread.Sleep(25); break; case iPodCommand.VolumeDown: - iPodVolumeDown.Write(true); + _iPodVolumeDown.Write(true); Thread.Sleep(50); - iPodVolumeDown.Write(false); + _iPodVolumeDown.Write(false); Thread.Sleep(25); break; } @@ -153,7 +151,7 @@ void ExecuteIPodCommand(object c) void EnqueueIPodCommand(iPodCommand command) { - iPodCommands.Enqueue(command); + _iPodCommands.Enqueue(command); } #endregion @@ -203,14 +201,14 @@ public override void MFLDialLong() public override bool RandomToggle() { // Fixing IsPlaying flag, when playing iPod was connected to paused CDC - isPlaying = !isPlaying; + _isPlaying = !_isPlaying; OnIsPlayingChanged(IsPlaying); return false; // Real status of iPod's shuffle-mode is unknown } public override void VolumeUp() { - if (canControlVolume) + if (_canControlVolume) { EnqueueIPodCommand(iPodCommand.VolumeUp); } @@ -218,7 +216,7 @@ public override void VolumeUp() public override void VolumeDown() { - if (canControlVolume) + if (_canControlVolume) { EnqueueIPodCommand(iPodCommand.VolumeDown); } @@ -228,11 +226,11 @@ public override bool IsPlaying { get { - return isPlaying; + return _isPlaying; } protected set { - if (isPlaying == value) + if (_isPlaying == value) { return; } @@ -249,7 +247,7 @@ protected set return; } PressIPodButton(true); - isPlaying = value; + _isPlaying = value; IsInVoiceOverMenu = false; OnIsPlayingChanged(value); } @@ -269,21 +267,21 @@ public bool IsInVoiceOverMenu { get { - if (isInVoiceOverMenu && (DateTime.Now - voiceOverMenuStarted).GetTotalSeconds() >= VoiceOverMenuTimeoutSeconds) + if (_isInVoiceOverMenu && (DateTime.Now - _voiceOverMenuStarted).GetTotalSeconds() >= VoiceOverMenuTimeoutSeconds) { IsInVoiceOverMenu = false; } - return isInVoiceOverMenu; + return _isInVoiceOverMenu; } private set { if (value) { OnStatusChanged("VoiceOver", PlayerEvent.Current); - voiceOverMenuStarted = DateTime.Now; + _voiceOverMenuStarted = DateTime.Now; PressIPodButton(false, 5000); } - isInVoiceOverMenu = value; + _isInVoiceOverMenu = value; } } diff --git a/imBMW/Shields/BluetoothOVC3860Shield.cs b/imBMW/Shields/BluetoothOVC3860Shield.cs index ccbfd4b..0c4d779 100644 --- a/imBMW/Shields/BluetoothOVC3860Shield.cs +++ b/imBMW/Shields/BluetoothOVC3860Shield.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Shields { public class BluetoothOVC3860Shield : ShieldBase diff --git a/imBMW/Shields/ShieldBase.cs b/imBMW/Shields/ShieldBase.cs index 40279a1..52024cf 100644 --- a/imBMW/Shields/ShieldBase.cs +++ b/imBMW/Shields/ShieldBase.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Shields { public class ShieldBase diff --git a/imBMW/Shields/ShieldManager.cs b/imBMW/Shields/ShieldManager.cs index 8a58948..f838d1c 100644 --- a/imBMW/Shields/ShieldManager.cs +++ b/imBMW/Shields/ShieldManager.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using System.Collections; using Microsoft.SPOT.Hardware; @@ -31,7 +29,7 @@ public static ArrayList InitShields(ShieldPort detectPort) public static ArrayList InitShields(Cpu.AnalogChannel detectPin) { - ArrayList shields = new ArrayList(); + var shields = new ArrayList(); var port = new AnalogInput(detectPin, 3300, 0, 12); var val = port.Read(); if (val == BluetoothOVC3860Shield.DetectValue) diff --git a/imBMW/Shields/ShieldPort.cs b/imBMW/Shields/ShieldPort.cs index 7dfc840..781688e 100644 --- a/imBMW/Shields/ShieldPort.cs +++ b/imBMW/Shields/ShieldPort.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.Shields { public enum ShieldPort diff --git a/imBMW/Tools/ASCIIEncoding.cs b/imBMW/Tools/ASCIIEncoding.cs index 461ca3b..0e6ff31 100644 --- a/imBMW/Tools/ASCIIEncoding.cs +++ b/imBMW/Tools/ASCIIEncoding.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace System.Text { // TODO diff --git a/imBMW/Tools/ArrayHelpers.cs b/imBMW/Tools/ArrayHelpers.cs index 60f53da..56aa049 100644 --- a/imBMW/Tools/ArrayHelpers.cs +++ b/imBMW/Tools/ArrayHelpers.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; namespace imBMW.Tools { @@ -22,7 +21,7 @@ public static byte[] SkipAndTake(this byte[] array, int skip, int take, bool ext { take = array.Length; } - byte[] result = new byte[take]; + var result = new byte[take]; if (extend && take > array.Length) { take = array.Length; @@ -163,9 +162,9 @@ public static void PasteASCII(this byte[] data, string s, int offset, int limit, alignOffset = (byte)(limit - len); } char[] chars = s.ToCharArray(); - byte c; for (byte i = 0; i < len; i++) { + byte c; if (chars[i] > 0xff) { c = 0x19; diff --git a/imBMW/Tools/DateTimeHelpers.cs b/imBMW/Tools/DateTimeHelpers.cs index ab1c80f..98b607c 100644 --- a/imBMW/Tools/DateTimeHelpers.cs +++ b/imBMW/Tools/DateTimeHelpers.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; namespace imBMW.Tools { diff --git a/imBMW/Tools/EnumConverter.cs b/imBMW/Tools/EnumConverter.cs index 3a01664..1fd8f22 100644 --- a/imBMW/Tools/EnumConverter.cs +++ b/imBMW/Tools/EnumConverter.cs @@ -4,6 +4,7 @@ namespace imBMW.Tools { + static class EnumConverter { /** @@ -25,7 +26,7 @@ public static string ToStringValue(this iPodViaHeadset.iPodCommand e) case iPodViaHeadset.iPodCommand.VolumeUp: return "VolumeUp"; case iPodViaHeadset.iPodCommand.VolumeDown: return "VolumeDown"; } - return "NotSpecified(" + e.ToString() + ")"; + return "NotSpecified(" + e + ")"; } public static string ToStringValue(this MFLButton e) @@ -33,12 +34,17 @@ public static string ToStringValue(this MFLButton e) switch (e) { case MFLButton.Next: return "Next"; + case MFLButton.NextHold: return "NextHold"; case MFLButton.Prev: return "Prev"; + case MFLButton.PrevHold: return "PrevHold"; case MFLButton.RT: return "RT"; + case MFLButton.RTRelease: return "RTRelease"; case MFLButton.Dial: return "Dial"; case MFLButton.DialLong: return "DialLong"; + case MFLButton.VolumeDown: return "VolumeDown"; + case MFLButton.VolumeUp: return "VolumeUp"; } - return "NotSpecified(" + e.ToString() + ")"; + return "NotSpecified(" + e + ")"; } public static string ToStringValue(this IgnitionState e) @@ -49,7 +55,7 @@ public static string ToStringValue(this IgnitionState e) case IgnitionState.Acc: return "Acc"; case IgnitionState.Ign: return "Ign"; } - return "NotSpecified(" + e.ToString() + ")"; + return "NotSpecified(" + e + ")"; } public static string ToStringValue(this RemoteKeyButton e) @@ -60,7 +66,7 @@ public static string ToStringValue(this RemoteKeyButton e) case RemoteKeyButton.Trunk: return "Trunk"; case RemoteKeyButton.Unlock: return "Unlock"; } - return "NotSpecified(" + e.ToString() + ")"; + return "NotSpecified(" + e + ")"; } public static string ToStringValue(this DeviceAddress e) @@ -110,7 +116,7 @@ public static string ToStringValue(this DeviceAddress e) case DeviceAddress.Unset: return "Unset"; case DeviceAddress.Unknown: return "Unknown"; } - return "NotSpecified(" + e.ToString() + ")"; + return "NotSpecified(" + e + ")"; } } } diff --git a/imBMW/Tools/ExtensionAttribute.cs b/imBMW/Tools/ExtensionAttribute.cs index d619ea0..e18741d 100644 --- a/imBMW/Tools/ExtensionAttribute.cs +++ b/imBMW/Tools/ExtensionAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | @@ -7,4 +5,4 @@ namespace System.Runtime.CompilerServices AttributeTargets.Method)] public sealed class ExtensionAttribute : Attribute { } -} \ No newline at end of file +} diff --git a/imBMW/Tools/Logger.cs b/imBMW/Tools/Logger.cs index adaf492..cd5bacf 100644 --- a/imBMW/Tools/Logger.cs +++ b/imBMW/Tools/Logger.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using imBMW.iBus; namespace imBMW.Tools @@ -19,8 +18,8 @@ public class LoggerArgs public readonly String Message; public readonly String LogString; public readonly LogPriority Priority; - public readonly Exception Exception; - public readonly iBus.Message iBusMessage; + //public readonly Exception Exception; + //public readonly Message iBusMessage; public readonly String PriorityTitle; public LoggerArgs(LogPriority priority, string message, string priorityTitle = null) @@ -81,7 +80,7 @@ public static void Info(string message, string priorityTitle = null) Log(LogPriority.Info, message, priorityTitle); } - public static void Info(iBus.Message message, string priorityTitle = null) + public static void Info(Message message, string priorityTitle = null) { Log(LogPriority.Info, message.ToPrettyString(true), priorityTitle); } @@ -91,7 +90,7 @@ public static void Warning(string message, string priorityTitle = null) Log(LogPriority.Warning, message, priorityTitle); } - public static void Warning(iBus.Message message, string priorityTitle = null) + public static void Warning(Message message, string priorityTitle = null) { Log(LogPriority.Warning, message.ToPrettyString(true), priorityTitle); } diff --git a/imBMW/Tools/Math.cs b/imBMW/Tools/Math.cs new file mode 100644 index 0000000..d8cacda --- /dev/null +++ b/imBMW/Tools/Math.cs @@ -0,0 +1,160 @@ +using System; + +namespace imBMW.Tools +{ + public class Math + { + public static readonly double PI = System.Math.PI; + public static readonly double E = System.Math.E; + + const double Sq2P1 = 2.414213562373095048802e0F; + const double Sq2M1 = .414213562373095048802e0F; + const double Pio2 = 1.570796326794896619231e0F; + const double Pio4 = .785398163397448309615e0F; + const double AtanP4 = .161536412982230228262e2F; + const double AtanP3 = .26842548195503973794141e3F; + const double AtanP2 = .11530293515404850115428136e4F; + const double AtanP1 = .178040631643319697105464587e4F; + const double AtanP0 = .89678597403663861959987488e3F; + const double AtanQ4 = .5895697050844462222791e2F; + const double AtanQ3 = .536265374031215315104235e3F; + const double AtanQ2 = .16667838148816337184521798e4F; + const double AtanQ1 = .207933497444540981287275926e4F; + const double AtanQ0 = .89678597403663861962481162e3F; + + public static double Pow(double x, double y) + { + return System.Math.Pow(x, y); + } + + public static double Sqrt(double x) + { + return System.Math.Pow(x, 0.5); + } + + public static double Atan(double x) + { + return x > 0.0F ? Atans(x) : -Atans(-x); + } + + public static double Asin(double x) + { + double sign = 1.0F; + + if (x < 0.0F) + { + x = -x; + sign = -1.0F; + } + + if (x > 1.0F) + { + throw new ArgumentOutOfRangeException("x"); + } + + double temp = Sqrt(1.0F - (x * x)); + + if (x > 0.7) + { + temp = Pio2 - Atan(temp / x); + } + else + { + temp = Atan(x / temp); + } + + return (sign * temp); + } + + public static double Cos(double x) + { + // This function is based on the work described in + // http://www.ganssle.com/approx/approx.pdf + + x = x % (PI * 2.0); + + // Make X positive if negative + if (x < 0) { x = 0.0F - x; } + + // Get quadrand + + // Quadrand 0, >-- Pi/2 + byte quadrand = 0; + + // Quadrand 1, Pi/2 -- Pi + if ((x > (PI / 2F)) & (x < (PI))) + { + quadrand = 1; + x = PI - x; + } + + // Quadrand 2, Pi -- 3Pi/2 + if ((x > (PI)) & (x < ((3F * PI) / 2))) + { + quadrand = 2; + x = PI - x; + } + + // Quadrand 3 - 3Pi/2 --> + if ((x > ((3F * PI) / 2))) + { + quadrand = 3; + x = (2F * PI) - x; + } + + // Constants used for approximation + const double c1 = 0.99999999999925182; + const double c2 = -0.49999999997024012; + const double c3 = 0.041666666473384543; + const double c4 = -0.001388888418000423; + const double c5 = 0.0000248010406484558; + const double c6 = -0.0000002752469638432; + const double c7 = 0.0000000019907856854; + + // X squared + double x2 = x * x; + + // Check quadrand + if ((quadrand == 0) | (quadrand == 3)) + { + // Return positive for quadrand 0, 3 + return (c1 + x2 * (c2 + x2 * (c3 + x2 * (c4 + x2 * (c5 + x2 * (c6 + c7 * x2)))))); + } + // Return negative for quadrand 1, 2 + return 0.0F - (c1 + x2 * (c2 + x2 * (c3 + x2 * (c4 + x2 * (c5 + x2 * (c6 + c7 * x2)))))); + } + + public static double Sin(double x) + { + return Cos((PI / 2.0F) - x); + } + + public static double Max(double x, double y) + { + return x >= y ? x : y; + } + + public static double Min(double x, double y) + { + return x <= y ? x : y; + } + + public static double ToRadians(double val) + { + return val * (PI / 180); + } + + private static double Atans(double x) + { + return x < Sq2M1 ? Atanx(x) : (x > Sq2P1 ? Pio2 - Atanx(1.0F / x) : Pio4 + Atanx((x - 1.0F) / (x + 1.0F))); + } + + private static double Atanx(double x) + { + double argsq = x * x; + double value = ((((AtanP4 * argsq + AtanP3) * argsq + AtanP2) * argsq + AtanP1) * argsq + AtanP0); + value = value / (((((argsq + AtanQ4) * argsq + AtanQ3) * argsq + AtanQ2) * argsq + AtanQ1) * argsq + AtanQ0); + return (value * x); + } + } +} diff --git a/imBMW/Tools/NumHelpers.cs b/imBMW/Tools/NumHelpers.cs index 14a97e8..3476230 100644 --- a/imBMW/Tools/NumHelpers.cs +++ b/imBMW/Tools/NumHelpers.cs @@ -1,15 +1,14 @@ using System; -using Microsoft.SPOT; namespace imBMW.Tools { public static class NumHelpers { - const string hexChars = "0123456789ABCDEF"; + const string HexChars = "0123456789ABCDEF"; public static String ToHex(this byte b) { - return hexChars[b >> 4].ToString() + hexChars[b & 0x0F].ToString(); + return HexChars[b >> 4] + HexChars[b & 0x0F].ToString(); } public static byte Invert(this byte b) @@ -24,7 +23,7 @@ public static bool HasBits(this byte b, byte bits) public static bool HasBit(this byte b, byte bitIndex) { - checkByteBitIndex(bitIndex); + CheckByteBitIndex(bitIndex); return b.HasBits((byte)(1 << bitIndex)); } @@ -35,7 +34,7 @@ public static byte RemoveBits(this byte b, byte bits) public static byte RemoveBit(this byte b, byte bitIndex) { - checkByteBitIndex(bitIndex); + CheckByteBitIndex(bitIndex); return b.RemoveBits((byte)(1 << bitIndex)); } @@ -46,13 +45,13 @@ public static byte AddBits(this byte b, byte bits) public static byte AddBit(this byte b, byte bitIndex) { - checkByteBitIndex(bitIndex); + CheckByteBitIndex(bitIndex); return b.AddBits((byte)(1 << bitIndex)); } - static void checkByteBitIndex(byte bitIndex) + static void CheckByteBitIndex(byte bitIndex) { - if (bitIndex < 0 || bitIndex > 7) + if (bitIndex > 7) { throw new ArgumentException("bitIndex"); } diff --git a/imBMW/Tools/Parse.cs b/imBMW/Tools/Parse.cs new file mode 100644 index 0000000..14ed8fe --- /dev/null +++ b/imBMW/Tools/Parse.cs @@ -0,0 +1,190 @@ +using System; + +namespace imBMW.Tools +{ + /// + /// Provides additional parsing operations + /// + public abstract class Parse + { + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseInt(string s, out int i) + { + i = 0; + try + { + i = int.Parse(s); + return true; + } + catch + { + return false; + } + } + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseShort(string s, out short i) + { + i = 0; + try + { + i = short.Parse(s); + return true; + } + catch + { + return false; + } + } + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseLong(string s, out long i) + { + i = 0; + try + { + i = long.Parse(s); + return true; + } + catch + { + return false; + } + } + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseDouble(string s, out double i) + { + i = 0; + try + { + i = double.Parse(s); + return true; + } + catch + { + return false; + } + } + + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseBool(string s, out bool val) + { + val = false; + try + { + if (s == "1" || s.ToUpper() == bool.TrueString.ToUpper()) + { + val = true; + + return true; + } + if (s == "0" || s.ToUpper() == bool.FalseString.ToUpper()) + { + return true; + } + + return false; + + } + catch + { + return false; + } + } + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseUInt(string s, out uint i) + { + i = 0; + try + { + i = uint.Parse(s); + return true; + } + catch + { + return false; + } + } + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseUShort(string s, out ushort i) + { + i = 0; + try + { + i = ushort.Parse(s); + return true; + } + catch + { + return false; + } + } + + public static ulong ParseULong(string s) + { + ulong i; + if (!TryParseULong(s, out i)) + throw new ApplicationException("Failed to parse"); + return i; + } + + /// + /// Attempt to parse the provided string value. + /// + /// String value to be parsed + /// Variable to set successfully parsed value to + /// True if parsing was successful + public static bool TryParseULong(string s, out ulong i) + { + i = 0; + try + { + i = ulong.Parse(s); + return true; + } + catch + { + return false; + } + } + } +} diff --git a/imBMW/Tools/QueueThreadWorker.cs b/imBMW/Tools/QueueThreadWorker.cs index d0993c8..24ebb17 100644 --- a/imBMW/Tools/QueueThreadWorker.cs +++ b/imBMW/Tools/QueueThreadWorker.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using System.Collections; using System.Threading; @@ -9,9 +8,9 @@ class QueueThreadWorker : Queue { public delegate void ProcessItem(object item); - Thread queueThread; - ProcessItem processItem; - object lockObj = new object(); + readonly Thread _queueThread; + readonly ProcessItem _processItem; + readonly object _lockObj = new object(); public QueueThreadWorker(ProcessItem processItem) { @@ -19,27 +18,19 @@ public QueueThreadWorker(ProcessItem processItem) { throw new ArgumentException("processItem is null"); } - this.processItem = processItem; - queueThread = new Thread(queueWorker); - queueThread.Priority = ThreadPriority.AboveNormal; - queueThread.Start(); + _processItem = processItem; + _queueThread = new Thread(QueueWorker) {Priority = ThreadPriority.AboveNormal}; + _queueThread.Start(); } - void queueWorker() + void QueueWorker() { - object m; while (true) { - lock (lockObj) + object m; + lock (_lockObj) { - if (Count > 0) - { - m = Dequeue(); - } - else - { - m = null; - } + m = Count > 0 ? Dequeue() : null; } if (m == null) { @@ -48,11 +39,11 @@ void queueWorker() } try { - processItem(m); + _processItem(m); } catch (Exception ex) { - Logger.Error(ex, "while processing QueueThreadWorker item '" + m.ToString() + "'"); + Logger.Error(ex, "while processing QueueThreadWorker item '" + m + "'"); } } } @@ -63,7 +54,7 @@ public override void Enqueue(object item) { throw new ArgumentException("item is null"); } - lock (lockObj) + lock (_lockObj) { base.Enqueue(item); CheckRunning(); @@ -76,7 +67,7 @@ public void EnqueueArray(params object[] items) { throw new ArgumentException("items is null"); } - lock (lockObj) + lock (_lockObj) { foreach (object item in items) { @@ -97,9 +88,9 @@ public void CheckRunning() * Tried AutoResetEvent instead of Suspend/Resume but no success because of strange slowness. */ // TODO Check ResetEvent on LDR and LED - if (queueThread.ThreadState == ThreadState.Suspended || queueThread.ThreadState == ThreadState.SuspendRequested) + if (_queueThread.ThreadState == ThreadState.Suspended || _queueThread.ThreadState == ThreadState.SuspendRequested) { - queueThread.Resume(); + _queueThread.Resume(); } } } diff --git a/imBMW/Tools/RCSwitch.cs b/imBMW/Tools/RCSwitch.cs new file mode 100644 index 0000000..94d51c6 --- /dev/null +++ b/imBMW/Tools/RCSwitch.cs @@ -0,0 +1,576 @@ +using System; +using Microsoft.SPOT.Hardware; + +namespace imBMW.Tools +{ + public class RCSwitch + { + #region Private fields + + private readonly OutputPort _pin; + private byte _protocol; + + #endregion + + #region Public constructor + + public RCSwitch(Cpu.Pin pin) + : this(pin, 1, 10) + { } + + public RCSwitch(Cpu.Pin pin, byte protocol, byte repeat) + { + _pin = new OutputPort(pin, false); + Protocol = protocol; + RepeatTransmit = repeat; + } + + #endregion + + #region Public properties + + public byte Protocol + { + get { return _protocol; } + set + { + if (value > 3) throw new ArgumentException("Only 1, 2, 3 protocol is supported"); + _protocol = value; + switch (_protocol) + { + case 1: + PulseLength = 350; + break; + case 2: + PulseLength = 650; + break; + case 3: + PulseLength = 100; + break; + } + } + } + + public ushort PulseLength { get; set; } + + public byte RepeatTransmit { get; set; } + + #endregion + + #region Private static methods + + private void DelayMicroseconds(int microseconds) + { + long delayTime = microseconds * 10; + long delayStart = Utility.GetMachineTime().Ticks; + while ((Utility.GetMachineTime().Ticks - delayStart) < delayTime) + { + } + } + + private static string DecimalToBinaryWithZeroFill(ulong dec, uint bitLength) + { + return DecimalToBinaryWithCharFill(dec, bitLength, '0'); + } + + private static string DecimalToBinaryWithCharFill(ulong dec, uint bitLength, char fill) + { + var bin = new char[64]; + uint i = 0; + + while (dec > 0) + { + bin[32 + i++] = ((dec & 1) > 0) ? '1' : fill; + dec = dec >> 1; + } + + for (uint j = 0; j < bitLength; j++) + { + if (j >= bitLength - i) + { + bin[j] = bin[31 + i - (j - (bitLength - i))]; + } + else + { + bin[j] = fill; + } + } + return new string(bin); + } + + /** + * Returns a string, representing the Code Word to be send. + */ + private static string GetCodeWordA(string group, string device, bool isOn) + { + var dipSwitches = new char[13]; + int i; + int j = 0; + + for (i = 0; i < 5; i++) + { + if (group[i] == '0') + { + dipSwitches[j++] = 'F'; + } + else + { + dipSwitches[j++] = '0'; + } + } + + for (i = 0; i < 5; i++) + { + if (device[i] == '0') + { + dipSwitches[j++] = 'F'; + } + else + { + dipSwitches[j++] = '0'; + } + } + + if (isOn) + { + dipSwitches[j++] = '0'; + dipSwitches[j] = 'F'; + } + else + { + dipSwitches[j++] = 'F'; + dipSwitches[j] = '0'; + } + + return new string(dipSwitches); + } + + /** + * Returns a char[13], representing the Code Word to be send. + * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used. + * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit) + * + * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ + * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S | + * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ + * + * nAddressCode Number of the switch group (1..4) + * nChannelCode Number of the switch itself (1..4) + * bStatus Whether to switch on (true) or off (false) + * + */ + private static string GetCodeWordB(int addressCode, int channelCode, bool status) + { + int returnPos = 0; + var r = new char[13]; + + string[] code = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" }; + if (addressCode < 1 || addressCode > 4 || channelCode < 1 || channelCode > 4) + { + return string.Empty; + } + for (int i = 0; i < 4; i++) + { + r[returnPos++] = code[addressCode][i]; + } + + for (int i = 0; i < 4; i++) + { + r[returnPos++] = code[channelCode][i]; + } + + r[returnPos++] = 'F'; + r[returnPos++] = 'F'; + r[returnPos++] = 'F'; + + r[returnPos] = status ? 'F' : '0'; + + return new string(r); + } + + /** + * Like getCodeWord (Type C = Intertechno) + */ + private static string GetCodeWordC(char family, uint group, uint device, bool status) + { + var r = new char[13]; + int returnPos = 0; + + if ((byte)family < 97 || (byte)family > 112 || group < 1 || group > 4 || device < 1 || device > 4) + { + return string.Empty; + } + + string sDeviceGroupCode = DecimalToBinaryWithZeroFill((device - 1) + (group - 1) * 4, 4); + string[] familycode = + { + "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F" + , "00FF", "F0FF", "0FFF", "FFFF" + }; + for (int i = 0; i < 4; i++) + { + r[returnPos++] = familycode[family - 97][i]; + } + for (int i = 0; i < 4; i++) + { + r[returnPos++] = (sDeviceGroupCode[3 - i] == '1' ? 'F' : '0'); + } + r[returnPos++] = '0'; + r[returnPos++] = 'F'; + r[returnPos++] = 'F'; + r[returnPos] = status ? 'F' : '0'; + return new string(r); + } + + /** + * Decoding for the REV Switch Type + * + * Returns a char[13], representing the Tristate to be send. + * A Code Word consists of 7 address bits and 5 command data bits. + * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high) + * + * +-------------------------------+--------------------------------+-----------------------+ + * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 | + * +-------------------------------+--------------------------------+-----------------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * Group Name of the switch group (A..D, resp. a..d) + * Device Number of the switch itself (1..3) + * bStatus Whether to switch on (true) or off (false) + * + */ + private static string GetCodeWordD(char group, int deviceCode, bool status) + { + var r = new char[13]; + int returnPos = 0; + + // Building 4 bits address + // (Potential problem if dec2binWcharfill not returning correct string) + string groupCode; + switch (group) + { + case 'a': + case 'A': + groupCode = DecimalToBinaryWithCharFill(8, 4, 'F'); + break; + case 'b': + case 'B': + groupCode = DecimalToBinaryWithCharFill(4, 4, 'F'); + break; + case 'c': + case 'C': + groupCode = DecimalToBinaryWithCharFill(2, 4, 'F'); + break; + case 'd': + case 'D': + groupCode = DecimalToBinaryWithCharFill(1, 4, 'F'); + break; + default: + return string.Empty; + } + + for (int i = 0; i < 4; i++) + { + r[returnPos++] = groupCode[i]; + } + + // Building 3 bits address + // (Potential problem if dec2binWcharfill not returning correct string) + string device; + switch (deviceCode) + { + case 1: + device = DecimalToBinaryWithCharFill(4, 3, 'F'); + break; + case 2: + device = DecimalToBinaryWithCharFill(2, 3, 'F'); + break; + case 3: + device = DecimalToBinaryWithCharFill(1, 3, 'F'); + break; + default: + return string.Empty; + } + + for (int i = 0; i < 3; i++) + r[returnPos++] = device[i]; + + // fill up rest with zeros + for (int i = 0; i < 5; i++) + r[returnPos++] = '0'; + + // encode on or off + if (status) + r[10] = '1'; + else + r[11] = '1'; + + // last position terminate string + return new string(r); + } + + #endregion + + #region Private methods + + private void Transmit(int highPulses, int lowPulses) + { + if (_pin != null) + { + _pin.Write(true); + DelayMicroseconds(PulseLength * highPulses); + _pin.Write(false); + DelayMicroseconds(PulseLength * lowPulses); + } + } + + /** + * Sends a "0" Bit + * _ + * Waveform Protocol 1: | |___ + * _ + * Waveform Protocol 2: | |__ + */ + private void Send0() + { + switch (Protocol) + { + case 1: + Transmit(1, 3); + break; + case 2: + Transmit(1, 2); + break; + case 3: + Transmit(4, 11); + break; + } + } + + /** + * Sends a "1" Bit + * ___ + * Waveform Protocol 1: | |_ + * __ + * Waveform Protocol 2: | |_ + */ + private void Send1() + { + switch (Protocol) + { + case 1: + Transmit(3, 1); + break; + case 2: + Transmit(2, 1); + break; + case 3: + Transmit(9, 6); + break; + } + } + + /** + * Sends a Tri-State "0" Bit + * _ _ + * Waveform: | |___| |___ + */ + private void SendT0() + { + Transmit(1, 3); + Transmit(1, 3); + } + + /** + * Sends a Tri-State "1" Bit + * ___ ___ + * Waveform: | |_| |_ + */ + private void SendT1() + { + Transmit(3, 1); + Transmit(3, 1); + } + + /** + * Sends a Tri-State "F" Bit + * _ ___ + * Waveform: | |___| |_ + */ + private void SendTF() + { + Transmit(1, 3); + Transmit(3, 1); + } + + /** + * Sends a "Sync" Bit + * _ + * Waveform Protocol 1: | |_______________________________ + * _ + * Waveform Protocol 2: | |__________ + */ + private void SendSync() + { + switch (Protocol) + { + case 1: + Transmit(1, 31); + break; + case 2: + Transmit(1, 10); + break; + case 3: + Transmit(1, 71); + break; + } + } + + #endregion + + #region Public methods + + public void Send(ulong code, uint length) + { + Send(DecimalToBinaryWithZeroFill(code, length)); + } + + public void Send(string codeWord) + { + for (int nRepeat = 0; nRepeat < RepeatTransmit; nRepeat++) + { + for (int i = 0; i < codeWord.Length; i++) + { + switch (codeWord[i]) + { + case '0': + Send0(); + break; + case '1': + Send1(); + break; + } + } + SendSync(); + } + } + + public void SendTriState(string codeWord) + { + for (int nRepeat = 0; nRepeat < RepeatTransmit; nRepeat++) + { + for (int i = 0; i < codeWord.Length; i++) + { + switch (codeWord[i]) + { + case '0': + SendT0(); + break; + case 'F': + SendTF(); + break; + case '1': + SendT1(); + break; + } + } + SendSync(); + } + } + + /** + * Switch a remote switch on (Type D REV) + * + * sGroup Code of the switch group (A,B,C,D) + * nDevice Number of the switch itself (1..3) + */ + public void SwitchOn(char group, int device) + { + SendTriState(GetCodeWordD(group, device, true)); + } + + /** + * Switch a remote switch off (Type D REV) + * + * sGroup Code of the switch group (A,B,C,D) + * nDevice Number of the switch itself (1..3) + */ + public void SwitchOff(char group, int device) + { + SendTriState(GetCodeWordD(group, device, false)); + } + + /** + * Switch a remote switch on (Type C Intertechno) + * + * sFamily Familycode (a..f) + * nGroup Number of group (1..4) + * nDevice Number of device (1..4) + */ + public void SwitchOn(char family, uint group, uint device) + { + SendTriState(GetCodeWordC(family, group, device, true)); + } + + /** + * Switch a remote switch off (Type C Intertechno) + * + * sFamily Familycode (a..f) + * nGroup Number of group (1..4) + * nDevice Number of device (1..4) + */ + public void SwitchOff(char family, uint group, uint device) + { + SendTriState(GetCodeWordC(family, group, device, false)); + } + + /** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * nAddressCode Number of the switch group (1..4) + * nChannelCode Number of the switch itself (1..4) + */ + public void SwitchOn(int addressCode, int channelCode) + { + SendTriState(GetCodeWordB(addressCode, channelCode, true)); + } + + /** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * nAddressCode Number of the switch group (1..4) + * nChannelCode Number of the switch itself (1..4) + */ + public void SwitchOff(int addressCode, int channelCode) + { + SendTriState(GetCodeWordB(addressCode, channelCode, false)); + } + + /** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ + public void SwitchOn(string group, string device) + { + SendTriState(GetCodeWordA(group, device, true)); + } + + /** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ + public void SwitchOff(string group, string device) + { + SendTriState(GetCodeWordA(group, device, false)); + } + + #endregion + } +} diff --git a/imBMW/Tools/StringBuilder.cs b/imBMW/Tools/StringBuilder.cs new file mode 100644 index 0000000..b3e010f --- /dev/null +++ b/imBMW/Tools/StringBuilder.cs @@ -0,0 +1,137 @@ +using System; + +namespace imBMW.Tools +{ + /// + /// Construct a larger string by appending strings together. + /// + public class StringBuilder + { + private const int InitialSize = 16; + private const int MinGrowthSize = 64; + + private char[] _content; + + /// + /// Public constructor + /// + public StringBuilder() + : this(InitialSize) + { + } + + /// + /// Public constructor + /// + /// Set initial builder capacity + public StringBuilder(int capacity) + { + _content = new char[capacity]; + } + + /// + /// Public constructor + /// + /// The initial content of the string builder + public StringBuilder(string initital) + { + _content = initital.ToCharArray(); + Length = _content.Length; + } + + /// + /// Append a character to the current string builder + /// + /// + public void Append(char c) + { + Append(new string(new[] { c })); + } + + /// + /// Append a string to the current string builder + /// + /// String to be appended. + public void Append(string toAppend) + { + int additionalSpaceRequired = (toAppend.Length + Length) - _content.Length; + + if (additionalSpaceRequired > 0) + { + // ensure at least minimum growth size is done to minimize future copying / manipulation + if (additionalSpaceRequired < MinGrowthSize) + { + additionalSpaceRequired = MinGrowthSize; + } + + var tmp = new char[_content.Length + additionalSpaceRequired]; + + // copy content to new array + Array.Copy(_content, tmp, Length); + + // replace the content array. + _content = tmp; + } + + // copy the new content to the holding array + Array.Copy(toAppend.ToCharArray(), 0, _content, Length, toAppend.Length); + Length += toAppend.Length; + } + + + /// + /// Append the provided line along with a new line. + /// + /// + public void AppendLine(string str) + { + Append(str); + Append("\r\n"); + } + + /// + /// Append to the string builder using format string and placeholder arguments + /// + /// String to be formatted + /// Arguments to be placed into the formatted string + public void AppendFormat(string format, params object[] args) + { + Append(StringHelpers.Format(format, args)); + } + + /// + /// Gets the length of the string builder. + /// + public int Length { get; private set; } + + /// + /// Gets char at specified position. + /// + /// Position to return char for. + /// Char is returned. + public int Get(int index) + { + if (index >= Length) throw new ArgumentException("Invalid index length"); + if (Length == 0) return 0; + + return _content[index]; + } + + /// + /// Clear the current string builder back to an empty string. + /// + public void Clear() + { + Length = 0; + } + + /// + /// Get the final built string. + /// + /// + public override string ToString() + { + return new string(_content, 0, Length); + } + } +} diff --git a/imBMW/Tools/StringHelpers.cs b/imBMW/Tools/StringHelpers.cs index 3045cd2..2e3efa1 100644 --- a/imBMW/Tools/StringHelpers.cs +++ b/imBMW/Tools/StringHelpers.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using System.Text; namespace imBMW.Tools @@ -16,6 +15,37 @@ public static class CharIcons public static class StringHelpers { + /// + /// Replace all occurrences of the 'find' string with the 'replace' string. + /// + /// Original string to operate on + /// String to find within the original string + /// String to be used in place of the find string + /// Final string after all instances have been replaced. + public static string Replace(this string content, string find, string replace) + { + const int startFrom = 0; + int findItemLength = find.Length; + + int firstFound; + var returning = new StringBuilder(); + + string workingString = content; + + while ((firstFound = workingString.IndexOf(find, startFrom)) >= 0) + { + returning.Append(workingString.Substring(0, firstFound)); + returning.Append(replace); + + // the remaining part of the string. + workingString = workingString.Substring(firstFound + findItemLength, workingString.Length - (firstFound + findItemLength)); + } + + returning.Append(workingString); + + return returning.ToString(); + } + /// /// Prepends chars to string to reach specified length /// @@ -35,7 +65,7 @@ public static string PrependToLength(this string s, uint length, char prepend = /// /// Appends chars to string to reach specified length /// - /// Char to append + /// Char to append /// String append to /// Required string length /// @@ -54,10 +84,9 @@ public static string UTF8ToASCII(this string s) // 0410 = А, 044F = я - UTF8 // TODO 1025 Ё 1105 ё var res = new byte[s.Length]; - char c; for (var i = 0; i < s.Length; i++) { - c = s[i]; + char c = s[i]; if (c >= 0x0410 && c <= 0x044F) { c = (char)(c - 0x0350); @@ -92,7 +121,7 @@ public static bool IsNumeric(this string str, bool positiveOnly = true, bool int { return false; } - foreach (var c in str) + foreach (var c in str.ToCharArray()) { if (!c.IsNumeric()) { @@ -118,5 +147,234 @@ public static bool IsNumeric(this char c) { return c >= '0' && c <= '9'; } + + /// + /// Replaces one or more format items in a specified string with the string representation of a specified object. + /// + /// A composite format string. + /// The object to format. + /// A copy of format in which any format items are replaced by the string representation of arg0. + /// format or args is null + public static string Format(string format, object arg) + { + return Format(format, new[] { arg }); + } + + private const string FormatInvalidMessage = "Format string is not valid"; + + /// + /// Format the given string using the provided collection of objects. + /// + /// A composite format string. + /// An object array that contains zero or more objects to format. + /// A copy of format in which the format items have been replaced by the string representation of the corresponding objects in args. + /// format or args is null + /// + /// x = StringUtility.Format("Quick brown {0}","fox"); + /// + public static string Format(string format, params object[] args) + { + if (format == null) + throw new ArgumentNullException("format"); + + if (args == null) + throw new ArgumentNullException("args"); + + // Validate the structure of the format string. + ValidateFormatString(format); + + var bld = new StringBuilder(); + + int endOfLastMatch = 0; + int starting = 0; + + while (starting >= 0) + { + starting = format.IndexOf('{', starting); + + if (starting >= 0) + { + if (starting != format.Length - 1) + { + if (format[starting + 1] == '{') + { + // escaped starting bracket. + starting = starting + 2; + continue; + } + bool found = false; + int endsearch = format.IndexOf('}', starting); + + while (endsearch > starting) + { + if (endsearch != (format.Length - 1) && format[endsearch + 1] == '}') + { + // escaped ending bracket + endsearch = endsearch + 2; + } + else + { + if (starting != endOfLastMatch) + { + string t = format.Substring(endOfLastMatch, starting - endOfLastMatch); + t = t.Replace("{{", "{"); // get rid of the escaped brace + t = t.Replace("}}", "}"); // get rid of the escaped brace + bld.Append(t); + } + + // we have a winner + string fmt = format.Substring(starting, endsearch - starting + 1); + + if (fmt.Length >= 3) + { + fmt = fmt.Substring(1, fmt.Length - 2); + + string[] indexFormat = fmt.Split(new[] { ':' }); + + string formatString = string.Empty; + + if (indexFormat.Length == 2) + { + formatString = indexFormat[1]; + } + + int index; + + // no format, just number + if (Parse.TryParseInt(indexFormat[0], out index)) + { + bld.Append(FormatParameter(args[index], formatString)); + } + else + { + throw new ApplicationException(FormatInvalidMessage); + } + } + + endOfLastMatch = endsearch + 1; + + found = true; + starting = endsearch + 1; + break; + } + + + endsearch = format.IndexOf('}', endsearch); + } + // need to find the ending point + + if (!found) + { + throw new ApplicationException(FormatInvalidMessage); + } + } + else + { + // invalid + throw new ApplicationException(FormatInvalidMessage); + } + + } + + } + + // copy any additional remaining part of the format string. + if (endOfLastMatch != format.Length) + { + bld.Append(format.Substring(endOfLastMatch, format.Length - endOfLastMatch)); + } + + return bld.ToString(); + } + + private static void ValidateFormatString(string format) + { + char expected = '{'; + + int i = 0; + + while ((i = format.IndexOfAny(new[] { '{', '}' }, i)) >= 0) + { + if (i < (format.Length - 1) && format[i] == format[i + 1]) + { + // escaped brace. continue looking. + i = i + 2; + continue; + } + if (format[i] != expected) + { + // badly formed string. + throw new ApplicationException(FormatInvalidMessage); + } + // move it along. + i++; + // expected it. + expected = expected == '{' ? '}' : '{'; + } + + if (expected == '}') + { + // orphaned opening brace. Bad format. + throw new ApplicationException(FormatInvalidMessage); + } + } + + /// + /// Format the provided object using the provided format string. + /// + /// Object to be formatted + /// Format string to be applied to the object + /// Formatted string for the object + private static string FormatParameter(object p, string formatString) + { + if (formatString == string.Empty) + return p.ToString(); + + if (p as IFormattable != null) + { + return ((IFormattable)p).ToString(formatString, null); + } + if (p is DateTime) + { + return ((DateTime)p).ToString(formatString); + } + if (p is Double) + { + return ((Double)p).ToString(formatString); + } + if (p is Int16) + { + return ((Int16)p).ToString(formatString); + } + if (p is Int32) + { + return ((Int32)p).ToString(formatString); + } + if (p is Int64) + { + return ((Int64)p).ToString(formatString); + } + if (p is SByte) + { + return ((SByte)p).ToString(formatString); + } + if (p is Single) + { + return ((Single)p).ToString(formatString); + } + if (p is UInt16) + { + return ((UInt16)p).ToString(formatString); + } + if (p is UInt32) + { + return ((UInt32)p).ToString(formatString); + } + if (p is UInt64) + { + return ((UInt64)p).ToString(formatString); + } + return p.ToString(); + } } } diff --git a/imBMW/iBus/DeviceAddress.cs b/imBMW/iBus/DeviceAddress.cs index fe8d838..ed73456 100644 --- a/imBMW/iBus/DeviceAddress.cs +++ b/imBMW/iBus/DeviceAddress.cs @@ -1,6 +1,3 @@ -using System; -using System.Reflection; - namespace imBMW.iBus { public enum DeviceAddress : short @@ -48,5 +45,4 @@ public enum DeviceAddress : short Unset = 0x100, Unknown = 0x101 } - } \ No newline at end of file diff --git a/imBMW/iBus/Devices/Emulators/BordmonitorAUX.cs b/imBMW/iBus/Devices/Emulators/BordmonitorAUX.cs index fed0d03..5cf763d 100644 --- a/imBMW/iBus/Devices/Emulators/BordmonitorAUX.cs +++ b/imBMW/iBus/Devices/Emulators/BordmonitorAUX.cs @@ -1,28 +1,23 @@ -using System; -using Microsoft.SPOT; using imBMW.Multimedia; using imBMW.iBus.Devices.Real; -using System.Threading; using imBMW.Tools; -using imBMW.Features.Menu.Screens; -using imBMW.Features.Menu; -using imBMW.Features.Localizations; namespace imBMW.iBus.Devices.Emulators { public class BordmonitorAUX : MediaEmulator { - bool isRadioActive = false; - bool isAUXSelected = false; + bool _isRadioActive; + bool _isAUXSelected; #region Messages - static Message MessageAUXHighVolumeP6 = new Message(DeviceAddress.OnBoardMonitor, DeviceAddress.Radio, "Set AUX high volume", 0x48, 0x03); + static readonly Message MessageAUXHighVolumeP6 = new Message(DeviceAddress.OnBoardMonitor, DeviceAddress.Radio, "Set AUX high volume", 0x48, 0x03); - static byte[] DataCD = new byte[] { 0x23, 0x62, 0x10, 0x43, 0x44 }; - static byte[] DataCDStartPlaying = new byte[] { 0x38, 0x03, 0x00 }; - static byte[] DataFM = new byte[] { 0xA5, 0x62, 0x01, 0x41, 0x20, 0x20, 0x46, 0x4D, 0x20 }; - static byte[] DataAM = new byte[] { 0xA5, 0x62, 0x01, 0x41, 0x20, 0x20, 0x41, 0x4D, 0x20 }; + static readonly byte[] DataCD = { 0x23, 0x62, 0x10, 0x43, 0x44 }; + + static readonly byte[] DataCdStartPlaying = { 0x38, 0x03, 0x00 }; + static readonly byte[] DataFM = { 0xA5, 0x62, 0x01, 0x41, 0x20, 0x20, 0x46, 0x4D, 0x20 }; + static readonly byte[] DataAM = { 0xA5, 0x62, 0x01, 0x41, 0x20, 0x20, 0x41, 0x4D, 0x20 }; #endregion @@ -50,7 +45,7 @@ void ProcessRadioMessage(Message m) { IsAUXSelected = true; } - else if (m.Data.Compare(DataFM) || m.Data.Compare(DataAM) || m.Data.StartsWith(DataCDStartPlaying)) + else if (m.Data.Compare(DataFM) || m.Data.Compare(DataAM) || m.Data.StartsWith(DataCdStartPlaying)) { IsAUXSelected = false; } @@ -69,7 +64,7 @@ protected override void OnIsEnabledChanged(bool isEnabled, bool fire = true) Play(); } - base.OnIsEnabledChanged(isEnabled); + base.OnIsEnabledChanged(isEnabled, fire); if (!isEnabled) { @@ -80,28 +75,28 @@ protected override void OnIsEnabledChanged(bool isEnabled, bool fire = true) public bool IsRadioActive { - get { return isRadioActive; } + get { return _isRadioActive; } set { - if (isRadioActive == value) + if (_isRadioActive == value) { return; } - isRadioActive = value; + _isRadioActive = value; CheckAuxOn(); } } public bool IsAUXSelected { - get { return isAUXSelected; } + get { return _isAUXSelected; } set { - if (isAUXSelected == value) + if (_isAUXSelected == value) { return; } - isAUXSelected = value; + _isAUXSelected = value; CheckAuxOn(); if (value) { @@ -111,6 +106,5 @@ public bool IsAUXSelected } #endregion - } } diff --git a/imBMW/iBus/Devices/Emulators/CDChanger.cs b/imBMW/iBus/Devices/Emulators/CDChanger.cs index b9dc68f..6593db3 100644 --- a/imBMW/iBus/Devices/Emulators/CDChanger.cs +++ b/imBMW/iBus/Devices/Emulators/CDChanger.cs @@ -1,9 +1,5 @@ -using System; -using Microsoft.SPOT; -using Microsoft.SPOT.Hardware; using System.Threading; using imBMW.Tools; -using imBMW.iBus.Devices.Real; using imBMW.Multimedia; namespace imBMW.iBus.Devices.Emulators @@ -12,22 +8,22 @@ public class CDChanger : MediaEmulator { const int StopDelayMilliseconds = 1000; - Thread announceThread; - Timer stopDelay; + readonly Thread _announceThread; + Timer _stopDelay; #region Messages - static Message MessagePollResponse = new Message(DeviceAddress.CDChanger, DeviceAddress.Broadcast, 0x02, 0x00); - static Message MessageAnnounce = new Message(DeviceAddress.CDChanger, DeviceAddress.Broadcast, 0x02, 0x01); - static Message MessagePlayingDisk1Track1 = new Message(DeviceAddress.CDChanger, DeviceAddress.Radio, "Playing D1 T1", 0x39, 0x02, 0x09, 0x00, 0x3F, 0x00, 0x01, 0x01); // was 39 00 09 - static Message MessageStoppedDisk1Track1 = new Message(DeviceAddress.CDChanger, DeviceAddress.Radio, "Stopped D1 T1", 0x39, 0x00, 0x02, 0x00, 0x3F, 0x00, 0x01, 0x01); // try 39 00 0C ? - static Message MessagePausedDisk1Track1 = new Message(DeviceAddress.CDChanger, DeviceAddress.Radio, "Paused D1 T1", 0x39, 0x01, 0x0C, 0x00, 0x3F, 0x00, 0x01, 0x01); + static readonly Message MessagePollResponse = new Message(DeviceAddress.CDChanger, DeviceAddress.Broadcast, 0x02, 0x00); + static readonly Message MessageAnnounce = new Message(DeviceAddress.CDChanger, DeviceAddress.Broadcast, 0x02, 0x01); + static readonly Message MessagePlayingDisk1Track1 = new Message(DeviceAddress.CDChanger, DeviceAddress.Radio, "Playing D1 T1", 0x39, 0x02, 0x09, 0x00, 0x3F, 0x00, 0x01, 0x01); // was 39 00 09 + static readonly Message MessageStoppedDisk1Track1 = new Message(DeviceAddress.CDChanger, DeviceAddress.Radio, "Stopped D1 T1", 0x39, 0x00, 0x02, 0x00, 0x3F, 0x00, 0x01, 0x01); // try 39 00 0C ? + static readonly Message MessagePausedDisk1Track1 = new Message(DeviceAddress.CDChanger, DeviceAddress.Radio, "Paused D1 T1", 0x39, 0x01, 0x0C, 0x00, 0x3F, 0x00, 0x01, 0x01); - static byte[] DataCurrentDiskTrackRequest = new byte[] { 0x38, 0x00, 0x00 }; - static byte[] DataStop = new byte[] { 0x38, 0x01, 0x00 }; - static byte[] DataPause = new byte[] { 0x38, 0x02, 0x00 }; - static byte[] DataPlay = new byte[] { 0x38, 0x03, 0x00 }; - static byte[] DataRandomPlay = new byte[] { 0x38, 0x08, 0x01 }; + static readonly byte[] DataCurrentDiskTrackRequest = { 0x38, 0x00, 0x00 }; + static readonly byte[] DataStop = { 0x38, 0x01, 0x00 }; + static readonly byte[] DataPause = { 0x38, 0x02, 0x00 }; + static readonly byte[] DataPlay = { 0x38, 0x03, 0x00 }; + static readonly byte[] DataRandomPlay = { 0x38, 0x08, 0x01 }; #endregion @@ -36,8 +32,8 @@ public CDChanger(IAudioPlayer player) { Manager.AddMessageReceiverForDestinationDevice(DeviceAddress.CDChanger, ProcessCDCMessage); - announceThread = new Thread(announce); - announceThread.Start(); + _announceThread = new Thread(Announce); + _announceThread.Start(); } #region Player control @@ -139,10 +135,10 @@ protected override void PlayPauseToggle() void CancelStopDelay() { - if (stopDelay != null) + if (_stopDelay != null) { - stopDelay.Dispose(); - stopDelay = null; + _stopDelay.Dispose(); + _stopDelay = null; } } @@ -162,9 +158,9 @@ protected override void OnIsEnabledChanged(bool isEnabled, bool fire = true) Play(); } - if (announceThread.ThreadState != ThreadState.Suspended) + if (_announceThread.ThreadState != ThreadState.Suspended) { - announceThread.Suspend(); + _announceThread.Suspend(); } } @@ -174,14 +170,14 @@ protected override void OnIsEnabledChanged(bool isEnabled, bool fire = true) { CancelStopDelay(); // Don't pause immediately - the radio can send "start play" command soon - stopDelay = new Timer(delegate + _stopDelay = new Timer(delegate { FireIsEnabledChanged(); Pause(); - if (announceThread.ThreadState == ThreadState.Suspended) + if (_announceThread.ThreadState == ThreadState.Suspended) { - announceThread.Resume(); + _announceThread.Resume(); } }, null, StopDelayMilliseconds, 0); } @@ -191,14 +187,7 @@ void ProcessCDCMessage(Message m) { if (m.Data.Compare(DataCurrentDiskTrackRequest)) { - if (Player.IsPlaying) - { - Manager.EnqueueMessage(MessagePlayingDisk1Track1); - } - else - { - Manager.EnqueueMessage(MessagePausedDisk1Track1); - } + Manager.EnqueueMessage(Player.IsPlaying ? MessagePlayingDisk1Track1 : MessagePausedDisk1Track1); m.ReceiverDescription = "CD status request"; } else if (m.Data.Compare(DataPlay)) @@ -216,14 +205,7 @@ void ProcessCDCMessage(Message m) else if (m.Data.Compare(MessageRegistry.DataPollRequest)) { Manager.EnqueueMessage(MessagePollResponse); - if (Player.IsPlaying) - { - Manager.EnqueueMessage(MessagePlayingDisk1Track1); - } - else - { - Manager.EnqueueMessage(MessagePausedDisk1Track1); - } + Manager.EnqueueMessage(Player.IsPlaying ? MessagePlayingDisk1Track1 : MessagePausedDisk1Track1); } else if (m.Data.Compare(DataRandomPlay)) { @@ -246,7 +228,7 @@ void ProcessCDCMessage(Message m) } } - static void announce() + static void Announce() { while (true) { diff --git a/imBMW/iBus/Devices/Emulators/MediaEmulator.cs b/imBMW/iBus/Devices/Emulators/MediaEmulator.cs index 8c1f5b0..75e097c 100644 --- a/imBMW/iBus/Devices/Emulators/MediaEmulator.cs +++ b/imBMW/iBus/Devices/Emulators/MediaEmulator.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using imBMW.iBus.Devices.Real; using imBMW.Multimedia; @@ -11,10 +10,10 @@ namespace imBMW.iBus.Devices.Emulators public abstract class MediaEmulator { - private bool isEnabled; - private IAudioPlayer player; + private bool _isEnabled; + private IAudioPlayer _player; - public MediaEmulator(IAudioPlayer player) + protected MediaEmulator(IAudioPlayer player) { Player = player; @@ -23,14 +22,14 @@ public MediaEmulator(IAudioPlayer player) public bool IsEnabled { - get { return isEnabled; } + get { return _isEnabled; } protected set { - if (isEnabled == value) + if (_isEnabled == value) { return; } - isEnabled = value; + _isEnabled = value; OnIsEnabledChanged(value); } } @@ -63,7 +62,7 @@ public IAudioPlayer Player { get { - return player; + return _player; } set { @@ -71,11 +70,11 @@ public IAudioPlayer Player { throw new ArgumentNullException(); } - if (player != null) + if (_player != null) { - UnsetPlayer(player); + UnsetPlayer(_player); } - player = value; + _player = value; SetupPlayer(value); } } diff --git a/imBMW/iBus/Devices/Real/BodyModule.cs b/imBMW/iBus/Devices/Real/BodyModule.cs index 3cd6115..046b75b 100644 --- a/imBMW/iBus/Devices/Real/BodyModule.cs +++ b/imBMW/iBus/Devices/Real/BodyModule.cs @@ -1,4 +1,3 @@ -using System; using Microsoft.SPOT; using imBMW.Tools; @@ -29,45 +28,62 @@ public RemoteKeyEventArgs(RemoteKeyButton button) #endregion - public static class BodyModule { #region Messages - static Message MessageOpenTrunk = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open trunk", 0x0C, 0x95, 0x01); + static readonly Message MessageOpenTrunk = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open trunk", 0x0C, 0x95, 0x01); - static Message MessageLockDoors = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Lock doors", 0x0C, 0x4F, 0x01); // 0x0C, 0x97, 0x01 - static Message MessageLockDriverDoor = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Lock driver door", 0x0C, 0x47, 0x01); - static Message MessageUnlockDoors = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Unlock doors", 0x0C, 0x45, 0x01); // 0x0C, 0x03, 0x01 + static readonly Message MessageLockDoors = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Lock doors", 0x0C, 0x4F, 0x01); // 0x0C, 0x97, 0x01 + static readonly Message MessageLockDriverDoor = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Lock driver door", 0x0C, 0x47, 0x01); + static readonly Message MessageUnlockDoors = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Unlock doors", 0x0C, 0x45, 0x01); // 0x0C, 0x03, 0x01 //static Message MessageOpenWindows = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, 0x0C, 0x00, 0x65); - static Message MessageOpenWindowDriverFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open driver front window", 0x0C, 0x52, 0x01); - static Message MessageOpenWindowDriverRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open driver rear window", 0x0C, 0x41, 0x01); - static Message MessageOpenWindowPassengerFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open passenger front window", 0x0C, 0x54, 0x01); - static Message MessageOpenWindowPassengerRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open passenger rear window", 0x0C, 0x44, 0x01); + static readonly Message MessageOpenWindowDriverFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open driver front window", 0x0C, 0x52, 0x01); + static readonly Message MessageOpenWindowDriverRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open driver rear window", 0x0C, 0x41, 0x01); + static readonly Message MessageOpenWindowPassengerFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open passenger front window", 0x0C, 0x54, 0x01); + static readonly Message MessageOpenWindowPassengerRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open passenger rear window", 0x0C, 0x44, 0x01); + + static readonly Message MessageCloseWindowDriverFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close driver front window", 0x0C, 0x53, 0x01); + static readonly Message MessageCloseWindowDriverRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close driver rear window", 0x0C, 0x42, 0x01); + static readonly Message MessageCloseWindowPassengerFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close passenger front window", 0x0C, 0x55, 0x01); + static readonly Message MessageCloseWindowPassengerRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close passenger rear window", 0x0C, 0x43, 0x01); + + static readonly Message MessageOpenSunroof = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open sunroof", 0x0C, 0x7E, 0x01); + static readonly Message MessageCloseSunroof = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close sunroof", 0x0C, 0x7F, 0x01); + + static readonly Message MessageFoldDriverMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Fold driver mirror", 0x0C, 0x01, 0x31, 0x01); + static readonly Message MessageFoldPassengerMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Fold passenger mirror", 0x0C, 0x02, 0x31, 0x01); + static readonly Message MessageUnfoldDriverMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Unfold driver mirror", 0x0C, 0x01, 0x30, 0x01); + static readonly Message MessageUnfoldPassengerMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Unfold passenger mirror", 0x0C, 0x02, 0x30, 0x01); + + static readonly Message MessageFoldMirrorsE46 = new Message(DeviceAddress.MirrorMemorySecond, DeviceAddress.MirrorMemory, "Fold mirrors", 0x6D, 0x90); + static readonly Message MessageUnfoldMirrorsE46 = new Message(DeviceAddress.MirrorMemorySecond, DeviceAddress.MirrorMemory, "Unfold mirrors", 0x6D, 0xA0); - static Message MessageCloseWindowDriverFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close driver front window", 0x0C, 0x53, 0x01); - static Message MessageCloseWindowDriverRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close driver rear window", 0x0C, 0x42, 0x01); - static Message MessageCloseWindowPassengerFront = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close passenger front window", 0x0C, 0x55, 0x01); - static Message MessageCloseWindowPassengerRear = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close passenger rear window", 0x0C, 0x43, 0x01); + static readonly Message MessageGetAnalogValues = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Get analog values", 0x0B, 0x01); - static Message MessageOpenSunroof = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Open sunroof", 0x0C, 0x7E, 0x01); - static Message MessageCloseSunroof = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Close sunroof", 0x0C, 0x7F, 0x01); + private static readonly Message MessageTurnOffAllExteriorLights = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Turn off all exterior lights", 0x76, 0x00); + private static readonly Message MessageTurnOffInteriorLights = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Turn off all interior lights", 0x0C, 0x01, 0x01); - static Message MessageFoldDriverMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Fold driver mirror", 0x0C, 0x01, 0x31, 0x01); - static Message MessageFoldPassengerMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Fold passenger mirror", 0x0C, 0x02, 0x31, 0x01); - static Message MessageUnfoldDriverMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Unfold driver mirror", 0x0C, 0x01, 0x30, 0x01); - static Message MessageUnfoldPassengerMirrorE39 = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Unfold passenger mirror", 0x0C, 0x02, 0x30, 0x01); + private static readonly Message MessageTurnOnClownNose = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Turn on clown nose for 3 seconds", 0x0C, 0x4E, 0x01); + private static readonly Message MessageTurnOnInterorLights = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Turn on interior lights for 3 seconds", 0x0C, 0x60, 0x01); - static Message MessageFoldMirrorsE46 = new Message(DeviceAddress.MirrorMemorySecond, DeviceAddress.MirrorMemory, "Fold mirrors", 0x6D, 0x90); - static Message MessageUnfoldMirrorsE46 = new Message(DeviceAddress.MirrorMemorySecond, DeviceAddress.MirrorMemory, "Unfold mirrors", 0x6D, 0xA0); + private static readonly Message MessageFlashWarningLigths = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash warning lights", 0x76, 0x02); + private static readonly Message MessageFlashLowbeams = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash lowbeams", 0x76, 0x04); + private static readonly Message MessageFlashLowbeamsAndWarningLights = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash lowbeams and warning lights", 0x76, 0x06); + private static readonly Message MessageFlashHighbeams = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash highbeams", 0x76, 0x08); + private static readonly Message MessageFlashHighbeamsAndWarningLights = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash highbeams and warning lights", 0x76, 0x0A); + private static readonly Message MessageFlashHighbeamsAndLowbeams = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash highbeams and lowbeams", 0x76, 0x0C); + private static readonly Message MessageFlashHighbeamsAndLowbeamsAndWarningLights = new Message(DeviceAddress.BodyModule, DeviceAddress.GlobalBroadcastAddress, "Flash highbeams, lowbeams and warning lights", 0x76, 0x0E); + private static readonly Message MessageFlashDashBlinkers = new Message(DeviceAddress.LightControlModule, DeviceAddress.GlobalBroadcastAddress, "Flash dash blinkers", 0x5B, 0x60, 0x00, 0x04, 0x00); + private static readonly Message MessageFlashDashBlinkersFastSlowIntermitent = new Message(DeviceAddress.LightControlModule, DeviceAddress.GlobalBroadcastAddress, "Flash dash blinkers fast/slow intermittent", 0x5B, 0x60, 0x00, 0x80, 0x00); - static Message MessageGetAnalogValues = new Message(DeviceAddress.Diagnostic, DeviceAddress.BodyModule, "Get analog values", 0x0B, 0x01); + private static readonly Message MessageCycleExteriorLightning = new Message(DeviceAddress.Diagnostic, DeviceAddress.GlobalBroadcastAddress, "Cycle through exterior lighting patterns", 0x0C, 0x01, 0x01); #endregion - static double batteryVoltage; + static double _batteryVoltage; static BodyModule() { @@ -114,7 +130,7 @@ static void OnRemoteKeyButton(Message m, RemoteKeyButton button) public static double BatteryVoltage { - get { return batteryVoltage; } + get { return _batteryVoltage; } private set { // always notify to know that message was received @@ -122,7 +138,7 @@ private set { return; }*/ - batteryVoltage = value; + _batteryVoltage = value; var e = BatteryVoltageChanged; if (e != null) diff --git a/imBMW/iBus/Devices/Real/Bordmonitor.cs b/imBMW/iBus/Devices/Real/Bordmonitor.cs index dfc8b3a..20ccb15 100644 --- a/imBMW/iBus/Devices/Real/Bordmonitor.cs +++ b/imBMW/iBus/Devices/Real/Bordmonitor.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.SPOT; using imBMW.Tools; namespace imBMW.iBus.Devices.Real @@ -35,10 +34,10 @@ public static class Bordmonitor public static Message MessageDisableRadioMenu = new Message(DeviceAddress.GraphicsNavigationDriver, DeviceAddress.Radio, "Disable radio menu", 0x45, 0x02); // Thanks to RichardP (Intravee) for these two messages public static Message MessageEnableRadioMenu = new Message(DeviceAddress.GraphicsNavigationDriver, DeviceAddress.Radio, "Enable radio menu", 0x45, 0x00); - public static byte[] DataRadioOn = new byte[] { 0x4A, 0xFF }; - public static byte[] DataRadioOff = new byte[] { 0x4A, 0x00 }; - public static byte[] DataShowTitle = new byte[] { 0x23, 0x62, 0x10 }; - public static byte[] DataAUX = new byte[] { 0x23, 0x62, 0x10, 0x41, 0x55, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; + public static byte[] DataRadioOn = { 0x4A, 0xFF }; + public static byte[] DataRadioOff = { 0x4A, 0x00 }; + public static byte[] DataShowTitle = { 0x23, 0x62, 0x10 }; + public static byte[] DataAUX = { 0x23, 0x62, 0x10, 0x41, 0x55, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; public static bool MK2Mode { get; set; } @@ -62,27 +61,14 @@ public static Message ShowText(string s, TextAlign align, BordmonitorFields fiel data = new byte[] { 0xA5, 0x62, 0x01, 0x06 }; break; case BordmonitorFields.Item: - if (check) // TODO test MK2 length - { - len = 14; - } - else - { - len = 23; - } + // TODO test MK2 length + len = check ? 14 : 23; index += 0x40; /*if (index == 0x47) { index = 0x7; }*/ - if (MK2Mode) - { - data = new byte[] { 0xA5, 0x62, 0x00, (byte)index }; - } - else - { - data = new byte[] { 0x21, 0x60, 0x00, (byte)index }; - } + data = MK2Mode ? new byte[] { 0xA5, 0x62, 0x00, index } : new byte[] { 0x21, 0x60, 0x00, index }; break; default: throw new Exception("TODO"); @@ -94,7 +80,7 @@ public static Message ShowText(string s, TextAlign align, BordmonitorFields fiel { data[data.Length - 1] = 0x2A; } - var m = new Message(iBus.DeviceAddress.Radio, iBus.DeviceAddress.GraphicsNavigationDriver, "Show message on BM (" + index.ToHex() + "): " + s, data); + var m = new Message(DeviceAddress.Radio, DeviceAddress.GraphicsNavigationDriver, "Show message on BM (" + index.ToHex() + "): " + s, data); Manager.EnqueueMessage(m); return m; } diff --git a/imBMW/iBus/Devices/Real/Immobiliser.cs b/imBMW/iBus/Devices/Real/Immobiliser.cs index c244b83..ba741c3 100644 --- a/imBMW/iBus/Devices/Real/Immobiliser.cs +++ b/imBMW/iBus/Devices/Real/Immobiliser.cs @@ -1,4 +1,3 @@ -using System; using Microsoft.SPOT; using imBMW.Tools; @@ -22,7 +21,6 @@ public KeyEventArgs(byte keyNumber) #endregion - public static class Immobiliser { public static byte LastKeyInserted { get; private set; } diff --git a/imBMW/iBus/Devices/Real/InstrumentClusterElectronics.cs b/imBMW/iBus/Devices/Real/InstrumentClusterElectronics.cs index b60aa5d..baec509 100644 --- a/imBMW/iBus/Devices/Real/InstrumentClusterElectronics.cs +++ b/imBMW/iBus/Devices/Real/InstrumentClusterElectronics.cs @@ -27,10 +27,10 @@ public IgnitionEventArgs(IgnitionState current, IgnitionState previous) public class SpeedRPMEventArgs : EventArgs { - public uint Speed { get; private set; } - public uint RPM { get; private set; } + public ushort Speed { get; private set; } + public ushort RPM { get; private set; } - public SpeedRPMEventArgs(uint speed, uint rpm) + public SpeedRPMEventArgs(ushort speed, ushort rpm) { Speed = speed; RPM = rpm; @@ -49,27 +49,98 @@ public TemperatureEventArgs(sbyte outside, sbyte coolant) } } + public class VinEventArgs : EventArgs + { + public string Value { get; private set; } + + public VinEventArgs(string value) + { + Value = value; + } + } + + public class OdometerEventArgs : EventArgs + { + public uint Value { get; private set; } + + public OdometerEventArgs(uint value) + { + Value = value; + } + } + + public class ConsumptionEventArgs : EventArgs + { + public float Value { get; private set; } + + public ConsumptionEventArgs(float value) + { + Value = value; + } + } + + public class RangeEventArgs : EventArgs + { + public uint Value { get; private set; } + + public RangeEventArgs(uint value) + { + Value = value; + } + } + + public class AverageSpeedEventArgs : EventArgs + { + public ushort Value { get; set; } + + public AverageSpeedEventArgs(ushort value) + { + Value = value; + } + } + public delegate void IgnitionEventHandler(IgnitionEventArgs e); + public delegate void VinEventHandler(VinEventArgs e); + + public delegate void OdometerEventHandler(OdometerEventArgs e); + public delegate void SpeedRPMEventHandler(SpeedRPMEventArgs e); public delegate void TemperatureEventHandler(TemperatureEventArgs e); + public delegate void ConsumptionEventHandler(ConsumptionEventArgs e); + + public delegate void AverageSpeedEventHandler(AverageSpeedEventArgs e); + + public delegate void RangeEventHandler(RangeEventArgs e); + #endregion public static class InstrumentClusterElectronics { - static IgnitionState currentIgnitionState = IgnitionState.Off; + static IgnitionState _currentIgnitionState = IgnitionState.Off; - public static uint CurrentRPM { get; private set; } - public static uint CurrentSpeed { get; private set; } + public static ushort CurrentRPM { get; private set; } + public static ushort CurrentSpeed { get; private set; } + + public static string VIN { get; private set; } + public static uint Odometer { get; private set; } + + public static float Consumption1 { get; private set; } + public static float Consumption2 { get; private set; } + + public static uint Range { get; private set; } + public static ushort AverageSpeed { get; private set; } public static sbyte TemperatureOutside { get; private set; } public static sbyte TemperatureCoolant { get; private set; } - static Message MessageGong1 = new Message(DeviceAddress.Radio, DeviceAddress.InstrumentClusterElectronics, "Gong 1", 0x23, 0x62, 0x30, 0x37, 0x08); - static Message MessageGong2 = new Message(DeviceAddress.Radio, DeviceAddress.InstrumentClusterElectronics, "Gong 2", 0x23, 0x62, 0x30, 0x37, 0x10); + static readonly Message MessageGong1 = new Message(DeviceAddress.Radio, DeviceAddress.InstrumentClusterElectronics, "Gong 1", 0x23, 0x62, 0x30, 0x37, 0x08); + static readonly Message MessageGong2 = new Message(DeviceAddress.Radio, DeviceAddress.InstrumentClusterElectronics, "Gong 2", 0x23, 0x62, 0x30, 0x37, 0x10); + + private static bool _timeIsSet, _dateIsSet; static InstrumentClusterElectronics() { @@ -79,11 +150,45 @@ static InstrumentClusterElectronics() Manager.AddMessageReceiverForSourceDevice(DeviceAddress.InstrumentClusterElectronics, ProcessIKEMessage); } + private static bool ParseFloat(byte[] data, out float result) + { + result = 0; + var str = string.Empty; + for (int i = 3; i < data.Length; i++) + { + str += (char)(data[i]); + } + double d; + if (Parse.TryParseDouble(str, out d)) + { + result = (float)d; + return true; + } + return false; + } + + private static bool ParseInt(byte[] data, out int result) + { + result = 0; + var str = string.Empty; + for (int i = 3; i < data.Length; i++) + { + str += (char)(data[i]); + } + int d; + if (Parse.TryParseInt(str, out d)) + { + result = d; + return true; + } + return false; + } + static void ProcessIKEMessage(Message m) { if (m.Data.Length == 3 && m.Data[0] == 0x18) { - OnSpeedRPMChanged(((uint)m.Data[1]) * 2, ((uint)m.Data[2]) * 100); + OnSpeedRPMChanged((ushort)(m.Data[1] * 2), (ushort)(m.Data[2] * 100)); m.ReceiverDescription = "Speed " + CurrentSpeed + "km/h " + CurrentRPM + "RPM"; } else if (m.Data.Length == 2 && m.Data[0] == 0x11) @@ -108,11 +213,113 @@ static void ProcessIKEMessage(Message m) } m.ReceiverDescription = "Ignition " + CurrentIgnitionState.ToStringValue(); } + else if (m.Data[0] == 0x17 && m.Data.Length == 8) + { + OnOdometerChanged((uint)(m.Data[3] * 65536 + m.Data[2] * 256 + m.Data[1])); + m.ReceiverDescription = "Odometer " + Odometer + " km"; + } + else if (m.Data[0] == 0x54 && m.Data.Length == 14) + { + OnVinChanged("" + (char)m.Data[1] + (char)m.Data[2] + m.Data[3].ToHex() + m.Data[4].ToHex() + m.Data[5].ToHex().Substring(0, 7)); + m.ReceiverDescription = "VIN " + VIN; + } else if (m.Data.Length == 4 && m.Data[0] == 0x19) { OnTemperatureChanged((sbyte)m.Data[1], (sbyte)m.Data[2]); m.ReceiverDescription = "Temperature. Outside " + TemperatureOutside + "C, Coolant " + TemperatureCoolant + "C"; } + else if (m.Data[0] == 0x24 && m.Data.Length > 2) + { + switch (m.Data[1]) + { + case 0x01: + if (m.Data.Length == 10) + { + var hour = Convert.ToByte(new string(new[] { (char)m.Data[3], (char)m.Data[4] })); + var minutes = Convert.ToByte(new string(new[] { (char)m.Data[6], (char)m.Data[7] })); + var now = DateTime.Now; + var date = new DateTime(now.Year, now.Month, now.Day, hour, minutes, now.Second); + if (!_timeIsSet) + { + //Utility.SetLocalTime(date); + _timeIsSet = true; + } + m.ReceiverDescription = "Date & Time, " + date.ToString("yyyy-MM-dd HH:mm"); + } + break; + case 0x02: + if (m.Data.Length == 13) + { + var day = Convert.ToByte(new string(new[] { (char)m.Data[3], (char)m.Data[4] })); + var month = Convert.ToByte(new string(new[] { (char)m.Data[6], (char)m.Data[7] })); + var year = Convert.ToInt16(new string(new[] { (char)m.Data[9], (char)m.Data[10], (char)m.Data[11], (char)m.Data[12] })); + var now = DateTime.Now; + var date = new DateTime(year, month, day, now.Hour, now.Minute, now.Second); + if (!_dateIsSet) + { + //Utility.SetLocalTime(date); + _dateIsSet = true; + } + m.ReceiverDescription = "Date & Time, " + date.ToString("yyyy-MM-dd HH:mm"); + } + break; + case 0x03: + if (m.Data.Length == 8) + { + float temperature; + if (ParseFloat(m.Data, out temperature)) + { + //TemperatureOutside = (sbyte)temperature; + m.ReceiverDescription = "Outside temperature " + temperature + "C"; + } + } + break; + case 0x04: + if (m.Data.Length == 7) + { + float consumption; + if (ParseFloat(m.Data, out consumption)) + { + OnConsumptionChanged(true, consumption); + m.ReceiverDescription = "Consumption 1 " + Consumption1 + " l/km"; + } + } + break; + case 0x05: + if (m.Data.Length == 7) + { + float consumption; + if (ParseFloat(m.Data, out consumption)) + { + OnConsumptionChanged(false, consumption); + m.ReceiverDescription = "Consumption 2 " + Consumption2 + " l/km"; + } + } + break; + case 0x06: + if (m.Data.Length == 7) + { + int range; + if (ParseInt(m.Data, out range)) + { + OnRangeChanged((uint)range); + m.ReceiverDescription = "Range " + Range + " km"; + } + } + break; + case 0x0A: + if (m.Data.Length == 7) + { + float speed; + if (ParseFloat(m.Data, out speed)) + { + OnAverageSpeedChanged((ushort)speed); + m.ReceiverDescription = "Average speed " + AverageSpeed + " km/h"; + } + } + break; + } + } } public static void Gong1() @@ -129,26 +336,26 @@ public static IgnitionState CurrentIgnitionState { get { - return currentIgnitionState; + return _currentIgnitionState; } private set { - if (currentIgnitionState == value) + if (_currentIgnitionState == value) { return; } - var previous = currentIgnitionState; - currentIgnitionState = value; + var previous = _currentIgnitionState; + _currentIgnitionState = value; var e = IgnitionStateChanged; if (e != null) { - e(new IgnitionEventArgs(currentIgnitionState, previous)); + e(new IgnitionEventArgs(_currentIgnitionState, previous)); } - if (currentIgnitionState != IgnitionState.Ign) + if (_currentIgnitionState != IgnitionState.Ign) { OnSpeedRPMChanged(CurrentSpeed, 0); } - Logger.Info("Ignition " + currentIgnitionState.ToStringValue()); + Logger.Info("Ignition " + _currentIgnitionState.ToStringValue()); } } @@ -163,7 +370,7 @@ private static void OnTemperatureChanged(sbyte outside, sbyte coolant) } } - private static void OnSpeedRPMChanged(uint speed, uint rpm) + private static void OnSpeedRPMChanged(ushort speed, ushort rpm) { CurrentSpeed = speed; CurrentRPM = rpm; @@ -174,8 +381,72 @@ private static void OnSpeedRPMChanged(uint speed, uint rpm) } } + + private static void OnVinChanged(string vin) + { + VIN = vin; + var e = VinChanged; + if (e != null) + { + e(new VinEventArgs(vin)); + } + } + + private static void OnOdometerChanged(uint odometer) + { + Odometer = odometer; + var e = OdometerChanged; + if (e != null) + { + e(new OdometerEventArgs(odometer)); + } + } + + private static void OnAverageSpeedChanged(ushort averageSpeed) + { + AverageSpeed = averageSpeed; + var e = AverageSpeedChanged; + if (e != null) + { + e(new AverageSpeedEventArgs(averageSpeed)); + } + } + + private static void OnRangeChanged(uint range) + { + Range = range; + var e = RangeChanged; + if (e != null) + { + e(new RangeEventArgs(range)); + } + } + + private static void OnConsumptionChanged(bool isFirst, float value) + { + ConsumptionEventHandler e; + if (isFirst) + { + e = Consumption1Changed; + Consumption1 = value; + } + else + { + e = Consumption2Changed; + Consumption2 = value; + } + if (e != null) + { + e(new ConsumptionEventArgs(value)); + } + } + public static event IgnitionEventHandler IgnitionStateChanged; + public static event VinEventHandler VinChanged; + + public static event OdometerEventHandler OdometerChanged; + /// /// IKE sends speed and RPM every 2 sec /// @@ -185,5 +456,25 @@ private static void OnSpeedRPMChanged(uint speed, uint rpm) /// IKE sends temperature every TBD sec /// public static event TemperatureEventHandler TemperatureChanged; + + /// + /// IKE sends consumption1 information every TBD sec + /// + public static event ConsumptionEventHandler Consumption1Changed; + + /// + /// IKE sends consumption2 information every TBD sec + /// + public static event ConsumptionEventHandler Consumption2Changed; + + /// + /// IKE sends average speed information every TBD sec + /// + public static event AverageSpeedEventHandler AverageSpeedChanged; + + /// + /// IKE sends range information every TBD sec + /// + public static event RangeEventHandler RangeChanged; } } diff --git a/imBMW/iBus/Devices/Real/LightControlModule.cs b/imBMW/iBus/Devices/Real/LightControlModule.cs index f6387cc..54d4a32 100644 --- a/imBMW/iBus/Devices/Real/LightControlModule.cs +++ b/imBMW/iBus/Devices/Real/LightControlModule.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Tools; namespace imBMW.iBus.Devices.Real diff --git a/imBMW/iBus/Devices/Real/MultiFunctionSteeringWheel.cs b/imBMW/iBus/Devices/Real/MultiFunctionSteeringWheel.cs index d97ccd3..a5f1632 100644 --- a/imBMW/iBus/Devices/Real/MultiFunctionSteeringWheel.cs +++ b/imBMW/iBus/Devices/Real/MultiFunctionSteeringWheel.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Tools; namespace imBMW.iBus.Devices.Real @@ -9,8 +7,13 @@ namespace imBMW.iBus.Devices.Real public enum MFLButton { Next, + NextHold, Prev, + PrevHold, + VolumeUp, + VolumeDown, RT, + RTRelease, Dial, DialLong } @@ -19,13 +22,14 @@ public enum MFLButton #endregion - class MultiFunctionSteeringWheel { - static bool wasDialLongPressed; - static bool needSkipRT; + static bool _wasDialLongPressed; + static bool _wasNextLongPressed; + static bool _wasPrevLongPressed; + static bool _needSkipRt; - static Message MessagePhoneResponse = new Message(DeviceAddress.Telephone, DeviceAddress.Broadcast, 0x02, 0x00); + static readonly Message MessagePhoneResponse = new Message(DeviceAddress.Telephone, DeviceAddress.Broadcast, 0x02, 0x00); /** * For right RT button commands @@ -46,7 +50,7 @@ static void InstrumentClusterElectronics_IgnitionStateChanged(IgnitionEventArgs if (e.CurrentIgnitionState != IgnitionState.Off && e.PreviousIgnitionState == IgnitionState.Off) { // MFL sends RT 00 signal on ignition OFF -> ACC - needSkipRT = true; + _needSkipRt = true; } } @@ -59,22 +63,67 @@ static void ProcessMFLMessage(Message m) Manager.EnqueueMessage(MessagePhoneResponse); } } + else if (m.Data.Length == 2 && m.Data[0] == 0x32) + { + var btn = m.Data[1]; + switch (btn) + { + case 0x10: + OnButtonPressed(m, MFLButton.VolumeDown); + break; + case 0x11: + OnButtonPressed(m, MFLButton.VolumeUp); + break; + } + } else if (m.Data.Length == 2 && m.Data[0] == 0x3B) { var btn = m.Data[1]; switch (btn) { case 0x01: - OnButtonPressed(m, MFLButton.Next); + _wasNextLongPressed = false; + m.ReceiverDescription = "Next pressed"; + break; + case 0x11: + _wasNextLongPressed = true; + OnButtonPressed(m, MFLButton.NextHold); + m.ReceiverDescription = "Next long pressed"; + break; + case 0x21: + if (!_wasNextLongPressed) + { + OnButtonPressed(m, MFLButton.Next); + } + else + { + m.ReceiverDescription = "Next released"; + } + _wasNextLongPressed = false; break; - case 0x08: - OnButtonPressed(m, MFLButton.Prev); + _wasPrevLongPressed = false; + break; + case 0x18: + _wasPrevLongPressed = true; + OnButtonPressed(m, MFLButton.PrevHold); + break; + case 0x28: + if (!_wasPrevLongPressed) + { + OnButtonPressed(m, MFLButton.Prev); + } + else + { + m.ReceiverDescription = "Prev released"; + } + _wasPrevLongPressed = false; break; - case 0x40: case 0x00: - if (!needSkipRT || btn == 0x40) + case 0x02: + case 0x12: + if (!_needSkipRt || (btn == 0x40 || btn == 0x12)) { OnButtonPressed(m, MFLButton.RT); } @@ -82,21 +131,25 @@ static void ProcessMFLMessage(Message m) { m.ReceiverDescription = "RT (skipped)"; } - needSkipRT = false; + _needSkipRt = false; + break; + case 0x22: + if (!_needSkipRt) + { + OnButtonPressed(m, MFLButton.RTRelease); + } break; - case 0x80: - wasDialLongPressed = false; + _wasDialLongPressed = false; m.ReceiverDescription = "Dial pressed"; break; - case 0x90: - wasDialLongPressed = true; + _wasDialLongPressed = true; OnButtonPressed(m, MFLButton.DialLong); + m.ReceiverDescription = "Dial long pressed"; break; - case 0xA0: - if (!wasDialLongPressed) + if (!_wasDialLongPressed) { OnButtonPressed(m, MFLButton.Dial); } @@ -104,9 +157,8 @@ static void ProcessMFLMessage(Message m) { m.ReceiverDescription = "Dial released"; } - wasDialLongPressed = false; + _wasDialLongPressed = false; break; - default: m.ReceiverDescription = "Button unknown " + btn.ToHex(); break; diff --git a/imBMW/iBus/Devices/Real/Navigation.cs b/imBMW/iBus/Devices/Real/Navigation.cs new file mode 100644 index 0000000..735b177 --- /dev/null +++ b/imBMW/iBus/Devices/Real/Navigation.cs @@ -0,0 +1,241 @@ +using System; +using imBMW.Tools; +using Microsoft.SPOT; +using Math = imBMW.Tools.Math; + +namespace imBMW.iBus.Devices.Real +{ + public static class Navigation + { + #region Public static fields + + public static event CoordinatesChangedEventHandler CoordinatesChangedReceived; + + #endregion + + #region Private static fields + + private static bool _timeIsSet; + + #endregion + + #region Static constructor + + static Navigation() + { + Manager.AddMessageReceiverForSourceDevice(DeviceAddress.NavigationEurope, ProcessMessage); + } + + #endregion + + #region Public static properties + + public static Coordinate CurrentCoordinate { get; private set; } + public static string CurrentCity { get; private set; } + public static string CurrentStreet { get; private set; } + + #endregion + + #region Private static methods + + private static float CalculateCoordinates(byte degrees, byte minutes, byte seconds, byte secondsParts) + { + var deg = Convert.ToByte(degrees.ToHex()); + var min = Convert.ToByte(minutes.ToHex()) / 60f; + var sec = Convert.ToByte(seconds.ToHex()) + Convert.ToByte(secondsParts.ToHex()) / 100f; + sec = sec / 3600f; + return deg + min + sec; + } + + private static float CalculateAltitude(byte alt1, byte alt2) + { + return Convert.ToByte(alt1.ToHex()) * 100 + Convert.ToByte(alt2.ToHex()); + } + + private static void OnCoordinatesReceived(Message m) + { + var speed = InstrumentClusterElectronics.CurrentSpeed; + var dateTime = DateTime.UtcNow; + var latitude = CalculateCoordinates(m.Data[3], m.Data[4], m.Data[5], m.Data[6]); + var longitude = CalculateCoordinates(m.Data[8], m.Data[9], m.Data[10], m.Data[11]); + var altitude = 0f; + bool isFixed = m.Data[1] == 0x01; + if (isFixed) + { + altitude = CalculateAltitude(m.Data[12], m.Data[13]); + dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, + Convert.ToByte(m.Data[15].ToHex()), Convert.ToByte(m.Data[16].ToHex()), Convert.ToByte(m.Data[17].ToHex())); + isFixed = _timeIsSet; + } + var coordinates = new Coordinate(latitude, longitude, altitude, speed, dateTime, isFixed); + m.ReceiverDescription = coordinates.ToString(); + + CurrentCoordinate = coordinates; + + var args = new CoordinatesChangedEventArgs { NewCoordinates = coordinates }; + var e = CoordinatesChangedReceived; + if (e != null) + { + e(args); + } + } + + private static void ProcessMessage(Message m) + { + if (m.Data[0] == 0xA2 && m.Data.Length == 18) + { + OnCoordinatesReceived(m); + } + else if (m.Data[0] == 0xA4 && m.Data.Length == 33) + { + var builder = new StringBuilder(); + for (int i = 3; i < m.Data.Length; i++) + { + if (m.Data[i] == 0x00) break; + builder.Append((char)m.Data[i]); + } + if (m.Data[2] == 0x01) + { + CurrentCity = builder.ToString().TrimEnd(new[] { ';', ',' }); + m.ReceiverDescription = "City: " + CurrentCity; + } + else if (m.Data[2] == 0x02) + { + CurrentStreet = builder.ToString().TrimEnd(new[] { ';', ',' }); + m.ReceiverDescription = "Street: " + CurrentStreet; + } + else + { + m.ReceiverDescription = "Unknown: " + builder; + } + } + else if (m.Data[0] == 0x1F && m.Data.Length == 9) + { + var hour = Convert.ToByte(m.Data[2].ToHex()); + var minutes = Convert.ToByte(m.Data[3].ToHex()); + var day = Convert.ToByte(m.Data[4].ToHex()); + var month = Convert.ToByte(m.Data[6].ToHex()); + var year = Convert.ToByte(m.Data[7].ToHex()) * 100 + Convert.ToByte(m.Data[8].ToHex()); + var date = new DateTime(year, month, day, hour, minutes, 0); + if (!_timeIsSet) + { + //Utility.SetLocalTime(date); + _timeIsSet = true; + } + m.ReceiverDescription = "Date & Time, " + date.ToString("yyyy-MM-dd HH:mm"); + } + else if (m.Data[0] == 0x44 && m.Data.Length == 3) + { + if (m.Data[1] == 0x21 || m.Data[1] == 0x29) + { + int mult = m.Data[1] == 0x29 ? 10 : 1; + m.ReceiverDescription = "IKE Text, Distance: " + Convert.ToByte(m.Data[2].ToHex()) * mult; + } + else if (m.Data[1] == 0x20) + { + m.ReceiverDescription = "IKE Text, Clear"; + } + } + } + + #endregion + } + + public class Coordinate + { + #region Public constructors + + public Coordinate() + { + } + + public Coordinate(float latitude, float longitude, float altitude, + ushort speed, DateTime time, bool isFixed) + { + Altitude = altitude; + Latitude = latitude; + Longitude = longitude; + Speed = speed; + Time = time; + IsFixed = isFixed; + } + + #endregion + + #region Public properties + + public float Altitude { get; private set; } + + public float Latitude { get; private set; } + + public float Longitude { get; private set; } + + public ushort Speed { get; private set; } + + public bool IsFixed { get; private set; } + + public DateTime Time { get; private set; } + + #endregion + + #region Public methods + + public double Distance(float lat, float lng) + { + return Distance(Latitude, Longitude, lat, lng); + } + + public double Distance(Coordinate coordinate) + { + return Distance(Latitude, Longitude, coordinate.Latitude, coordinate.Longitude); + } + + #endregion + + #region Public static methods + + private const float EarthRadiusInKilometers = 6367f; + + public static double Distance(float lat1, float lng1, float lat2, float lng2) + { + return Distance(lat1, lng1, lat2, lng2, EarthRadiusInKilometers); + } + + #endregion + + #region Private static methods + + private static double Distance(float lat1, float lng1, float lat2, float lng2, float radius) + { + // Implements the Haversine formula http://en.wikipedia.org/wiki/Haversine_formula + var lat = Math.ToRadians(lat2 - lat1); + var lng = Math.ToRadians(lng2 - lng1); + var sinLat = Math.Sin(0.5 * lat); + var sinLng = Math.Sin(0.5 * lng); + var cosLat1 = Math.Cos(Math.ToRadians(lat1)); + var cosLat2 = Math.Cos(Math.ToRadians(lat2)); + var h1 = sinLat * sinLat + cosLat1 * cosLat2 * sinLng * sinLng; + var h2 = Math.Sqrt(h1); + var h3 = 2 * Math.Asin(Math.Min(1, h2)); + return radius * h3; + } + + #endregion + + #region Public overriden methods + + public override string ToString() + { + return StringHelpers.Format("{0} {1}, {2}m", Latitude, Longitude, Altitude); + } + + #endregion + } + + public class CoordinatesChangedEventArgs : EventArgs + { + public Coordinate NewCoordinates { get; set; } + } + + public delegate void CoordinatesChangedEventHandler(CoordinatesChangedEventArgs args); +} diff --git a/imBMW/iBus/Devices/Real/Radio.cs b/imBMW/iBus/Devices/Real/Radio.cs index f920e15..136751d 100644 --- a/imBMW/iBus/Devices/Real/Radio.cs +++ b/imBMW/iBus/Devices/Real/Radio.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Tools; using System.Threading; @@ -9,22 +7,22 @@ public static class Radio { public const byte DisplayTextMaxLen = 11; - const int displayTextDelay = 150; + const int DisplayTextDelay = 150; - static Timer displayTextDelayTimer; - static bool hasMID = false; + static Timer _displayTextDelayTimer; + static bool _hasMID; public static void Init() { - hasMID = Manager.FindDevice(DeviceAddress.MultiInfoDisplay); + _hasMID = Manager.FindDevice(DeviceAddress.MultiInfoDisplay); } static void ClearTimer() { - if (displayTextDelayTimer != null) + if (_displayTextDelayTimer != null) { - displayTextDelayTimer.Dispose(); - displayTextDelayTimer = null; + _displayTextDelayTimer.Dispose(); + _displayTextDelayTimer = null; } } @@ -32,17 +30,17 @@ public static void DisplayTextWithDelay(string s, TextAlign align = TextAlign.Le { ClearTimer(); - displayTextDelayTimer = new Timer(delegate + _displayTextDelayTimer = new Timer(delegate { DisplayText(s, align); - }, null, displayTextDelay, 0); + }, null, DisplayTextDelay, 0); } public static void DisplayText(string s, TextAlign align = TextAlign.Left) { ClearTimer(); - if (hasMID) + if (_hasMID) { DisplayTextMID(s, align); } @@ -54,7 +52,7 @@ public static void DisplayText(string s, TextAlign align = TextAlign.Left) private static void DisplayTextMID(string s, TextAlign align) { - byte[] data = new byte[] { 0x23, 0x40, 0x20 }; + byte[] data = { 0x23, 0x40, 0x20 }; data = data.PadRight(0x20, DisplayTextMaxLen); data.PasteASCII(s, 3, DisplayTextMaxLen, align); Manager.EnqueueMessage(new Message(DeviceAddress.Radio, DeviceAddress.MultiInfoDisplay, "Show text \"" + s + "\" on MID", data)); @@ -62,7 +60,7 @@ private static void DisplayTextMID(string s, TextAlign align) private static void DisplayTextRadio(string s, TextAlign align) { - byte[] data = new byte[] { 0x23, 0x42, 0x30 }; + byte[] data = { 0x23, 0x42, 0x30 }; data = data.PadRight(0x19, DisplayTextMaxLen); data.PasteASCII(s, 3, DisplayTextMaxLen, align); Manager.EnqueueMessage(new Message(DeviceAddress.Telephone, DeviceAddress.InstrumentClusterElectronics, "Show text \"" + s + "\" on the radio", data)); diff --git a/imBMW/iBus/Devices/Real/SeatMemory.cs b/imBMW/iBus/Devices/Real/SeatMemory.cs new file mode 100644 index 0000000..40b66a5 --- /dev/null +++ b/imBMW/iBus/Devices/Real/SeatMemory.cs @@ -0,0 +1,125 @@ +using Microsoft.SPOT; + +namespace imBMW.iBus.Devices.Real +{ + public static class SeatMemory + { + #region Private static readonly fields + + private static readonly Message MessageMoveToMemoryPosition1 = new Message(DeviceAddress.Diagnostic, DeviceAddress.SeatMemory, "Move to memory position 1", 0x0C, 0x02, 0x01, 0x00); + private static readonly Message MessageMoveToMemoryPosition2 = new Message(DeviceAddress.Diagnostic, DeviceAddress.SeatMemory, "Move to memory position 2", 0x0C, 0x02, 0x02, 0x00); + private static readonly Message MessageMoveToMemoryPosition3 = new Message(DeviceAddress.Diagnostic, DeviceAddress.SeatMemory, "Move to memory position 3", 0x0C, 0x02, 0x04, 0x00); + + #endregion + + #region Public static fields + + public static event SeatMemoryPositionChangedEventHandler SeatMemoryPositionChanged; + + #endregion + + #region Private fields + + private static SeatMemoryPosition _memoryPosition = SeatMemoryPosition.PositionUnknown; + + #endregion + + #region Static constructor + + static SeatMemory() + { + Manager.AddMessageReceiverForSourceOrDestinationDevice(DeviceAddress.SeatMemory, DeviceAddress.SeatMemory, ProcessMessage); + } + + #endregion + + #region Public static fields + + public static SeatMemoryPosition SeatPosition + { + get { return _memoryPosition; } + set + { + if (_memoryPosition != value) + { + ChangePosition(value); + OnSeatMemoryPositionChanged(value); + } + } + } + + #endregion + + #region Private static methods + + private static void ProcessMessage(Message m) + { + if (m.SourceDevice == DeviceAddress.SeatMemory) + { + if (m.Data[0] == 0x78 && m.Data.Length == 3) + { + var position = SeatMemoryPosition.PositionUnknown; + switch (m.Data[1]) + { + case 0x01: + position = SeatMemoryPosition.Position1; + break; + case 0x02: + position = SeatMemoryPosition.Position2; + break; + case 0x04: + position = SeatMemoryPosition.Position3; + break; + } + if (position != SeatMemoryPosition.PositionUnknown) + OnSeatMemoryPositionChanged(position); + } + } + } + + private static void OnSeatMemoryPositionChanged(SeatMemoryPosition newPosition) + { + if (_memoryPosition == newPosition) return; + + _memoryPosition = newPosition; + var e = SeatMemoryPositionChanged; + if (e != null) + { + e(new SeatMemoryPositionChangedEventArgs { Position = _memoryPosition }); + } + } + + private static void ChangePosition(SeatMemoryPosition newPosition) + { + switch (newPosition) + { + case SeatMemoryPosition.Position1: + Manager.EnqueueMessage(MessageMoveToMemoryPosition1); + break; + case SeatMemoryPosition.Position2: + Manager.EnqueueMessage(MessageMoveToMemoryPosition2); + break; + case SeatMemoryPosition.Position3: + Manager.EnqueueMessage(MessageMoveToMemoryPosition3); + break; + } + } + + #endregion + } + + public enum SeatMemoryPosition + { + PositionUnknown, + Position1, + Position2, + Position3 + } + + public class SeatMemoryPositionChangedEventArgs : EventArgs + { + public SeatMemoryPosition Position { get; set; } + } + + public delegate void SeatMemoryPositionChangedEventHandler(SeatMemoryPositionChangedEventArgs args); +} diff --git a/imBMW/iBus/Diagnostics/DBusConverter.cs b/imBMW/iBus/Diagnostics/DBusConverter.cs index 9168b4d..a0a0232 100644 --- a/imBMW/iBus/Diagnostics/DBusConverter.cs +++ b/imBMW/iBus/Diagnostics/DBusConverter.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.SPOT; - namespace imBMW.iBus.Diagnostics { public class DBusConverter diff --git a/imBMW/iBus/Diagnostics/DBusMessage.cs b/imBMW/iBus/Diagnostics/DBusMessage.cs index 77a4103..a2820fb 100644 --- a/imBMW/iBus/Diagnostics/DBusMessage.cs +++ b/imBMW/iBus/Diagnostics/DBusMessage.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Tools; namespace imBMW.iBus.Diagnostics @@ -46,7 +44,7 @@ public DBusMessage(byte destination, params byte[] data) return false; } - byte packetLength = (byte)(packet[1] + 2); + var packetLength = (byte)(packet[1] + 2); if (length < packetLength) { return false; @@ -67,7 +65,7 @@ public DBusMessage(byte destination, params byte[] data) return true; } - byte packetLength = (byte)(packet[1] + 2); + var packetLength = (byte)(packet[1] + 2); if (packetLength < PacketLengthMin || packetLength > PacketLengthMax) { diff --git a/imBMW/iBus/Manager.cs b/imBMW/iBus/Manager.cs index 9d0b327..469e290 100644 --- a/imBMW/iBus/Manager.cs +++ b/imBMW/iBus/Manager.cs @@ -1,7 +1,6 @@ using System; using Microsoft.SPOT; using System.Collections; -using Microsoft.SPOT.Hardware; using System.IO.Ports; using System.Threading; using imBMW.Tools; @@ -28,39 +27,38 @@ public MessageEventArgs(Message message) #endregion - public static class Manager { - static ISerialPort iBus; + static ISerialPort _iBus; public static void Init(ISerialPort port) { - messageWriteQueue = new QueueThreadWorker(SendMessage); + _messageWriteQueue = new QueueThreadWorker(SendMessage); //messageReadQueue = new QueueThreadWorker(ProcessMessage); - iBus = port; - iBus.DataReceived += new SerialDataReceivedEventHandler(iBus_DataReceived); + _iBus = port; + _iBus.DataReceived += iBus_DataReceived; } #region Message reading and processing //static QueueThreadWorker messageReadQueue; - const int messageReadTimeout = 16; // 2 * 30 * Message.PacketLengthMax / 8; // tested on 8byte message, got 30ms (real, instead of theoretical 8ms), and made 2x reserve - static DateTime lastMessage = DateTime.Now; - static byte[] messageBuffer = new byte[Message.PacketLengthMax]; - static int messageBufferLength = 0; - static object bufferSync = new object(); + const int MessageReadTimeout = 16; // 2 * 30 * Message.PacketLengthMax / 8; // tested on 8byte message, got 30ms (real, instead of theoretical 8ms), and made 2x reserve + static DateTime _lastMessage = DateTime.Now; + static byte[] _messageBuffer = new byte[Message.PacketLengthMax]; + static int _messageBufferLength; + static readonly object BufferSync = new object(); static void iBus_DataReceived(object sender, SerialDataReceivedEventArgs e) { - ISerialPort port = (ISerialPort)sender; + var port = (ISerialPort)sender; if (port.AvailableBytes == 0) { - Logger.Warning("Available bytes lost! " + port.ToString()); + Logger.Warning("Available bytes lost! " + port); return; } - lock (bufferSync) + lock (BufferSync) { byte[] data = port.ReadAvailable(); #if DEBUG @@ -78,30 +76,30 @@ static void iBus_DataReceived(object sender, SerialDataReceivedEventArgs e) } } #endif*/ - if (messageBufferLength + data.Length > messageBuffer.Length) + if (_messageBufferLength + data.Length > _messageBuffer.Length) { - Logger.Info("Buffer overflow. Extending it. " + port.ToString()); - byte[] newBuffer = new byte[messageBuffer.Length * 2]; - Array.Copy(messageBuffer, newBuffer, messageBufferLength); - messageBuffer = newBuffer; + Logger.Info("Buffer overflow. Extending it. " + port); + var newBuffer = new byte[_messageBuffer.Length * 2]; + Array.Copy(_messageBuffer, newBuffer, _messageBufferLength); + _messageBuffer = newBuffer; } if (data.Length == 1) { - messageBuffer[messageBufferLength++] = data[0]; + _messageBuffer[_messageBufferLength++] = data[0]; } else { - Array.Copy(data, 0, messageBuffer, messageBufferLength, data.Length); - messageBufferLength += data.Length; + Array.Copy(data, 0, _messageBuffer, _messageBufferLength, data.Length); + _messageBufferLength += data.Length; } - while (messageBufferLength >= Message.PacketLengthMin) + while (_messageBufferLength >= Message.PacketLengthMin) { - Message m = Message.TryCreate(messageBuffer, messageBufferLength); + Message m = Message.TryCreate(_messageBuffer, _messageBufferLength); if (m == null) { - if (!Message.CanStartWith(messageBuffer, messageBufferLength)) + if (!Message.CanStartWith(_messageBuffer, _messageBufferLength)) { - Logger.Warning("Buffer skip: non-iBus data detected: " + messageBuffer[0].ToHex()); + Logger.Warning("Buffer skip: non-iBus data detected: " + _messageBuffer[0].ToHex()); SkipBuffer(1); continue; } @@ -114,16 +112,16 @@ static void iBus_DataReceived(object sender, SerialDataReceivedEventArgs e) //messageReadQueue.Enqueue(m); SkipBuffer(m.PacketLength); } - lastMessage = DateTime.Now; + _lastMessage = DateTime.Now; } } static void SkipBuffer(byte count) { - messageBufferLength -= count; - if (messageBufferLength > 0) + _messageBufferLength -= count; + if (_messageBufferLength > 0) { - Array.Copy(messageBuffer, count, messageBuffer, 0, messageBufferLength); + Array.Copy(_messageBuffer, count, _messageBuffer, 0, _messageBufferLength); } } @@ -155,7 +153,7 @@ public static void ProcessMessage(object o) return; } - foreach (MessageReceiverRegistration receiver in messageReceiverList) + foreach (MessageReceiverRegistration receiver in MessageReceiverList) { try { @@ -227,7 +225,7 @@ public static void ProcessMessage(object o) #region Message writing and queue - static QueueThreadWorker messageWriteQueue; + static QueueThreadWorker _messageWriteQueue; static void SendMessage(object o) { @@ -249,7 +247,7 @@ static void SendMessage(object o) } } - iBus.Write(m.Packet); + _iBus.Write(m.Packet); #if DEBUG m.PerformanceInfo.TimeEndedProcessing = DateTime.Now; @@ -265,12 +263,12 @@ static void SendMessage(object o) e(args); } - Thread.Sleep(iBus.AfterWriteDelay); // Don't flood iBus + Thread.Sleep(_iBus.AfterWriteDelay); // Don't flood iBus } public static void EnqueueMessage(Message m) { - if (iBus is SerialPortHub) + if (_iBus is SerialPortHub) { SendMessage(m); return; @@ -278,12 +276,12 @@ public static void EnqueueMessage(Message m) #if DEBUG m.PerformanceInfo.TimeEnqueued = DateTime.Now; #endif - messageWriteQueue.Enqueue(m); + _messageWriteQueue.Enqueue(m); } public static void EnqueueMessage(params Message[] messages) { - if (iBus is SerialPortHub) + if (_iBus is SerialPortHub) { foreach (Message m in messages) { @@ -298,7 +296,7 @@ public static void EnqueueMessage(params Message[] messages) m.PerformanceInfo.TimeEnqueued = now; } #endif - messageWriteQueue.EnqueueArray(messages); + _messageWriteQueue.EnqueueArray(messages); } #endregion @@ -353,63 +351,63 @@ public MessageReceiverRegistration(DeviceAddress source, DeviceAddress destinati } } - static ArrayList messageReceiverList = new ArrayList(); + static readonly ArrayList MessageReceiverList = new ArrayList(); public static void AddMessageReceiverForSourceDevice(DeviceAddress source, MessageReceiver callback) { - messageReceiverList.Add(new MessageReceiverRegistration(source, DeviceAddress.Unset, callback, MessageReceiverRegistration.MatchType.Source)); + MessageReceiverList.Add(new MessageReceiverRegistration(source, DeviceAddress.Unset, callback, MessageReceiverRegistration.MatchType.Source)); } public static void AddMessageReceiverForDestinationDevice(DeviceAddress destination, MessageReceiver callback) { - messageReceiverList.Add(new MessageReceiverRegistration(DeviceAddress.Unset, destination, callback, MessageReceiverRegistration.MatchType.Destination)); + MessageReceiverList.Add(new MessageReceiverRegistration(DeviceAddress.Unset, destination, callback, MessageReceiverRegistration.MatchType.Destination)); } public static void AddMessageReceiverForSourceAndDestinationDevice(DeviceAddress source, DeviceAddress destination, MessageReceiver callback) { - messageReceiverList.Add(new MessageReceiverRegistration(source, destination, callback, MessageReceiverRegistration.MatchType.SourceAndDestination)); + MessageReceiverList.Add(new MessageReceiverRegistration(source, destination, callback, MessageReceiverRegistration.MatchType.SourceAndDestination)); } public static void AddMessageReceiverForSourceOrDestinationDevice(DeviceAddress source, DeviceAddress destination, MessageReceiver callback) { - messageReceiverList.Add(new MessageReceiverRegistration(source, destination, callback, MessageReceiverRegistration.MatchType.SourceOrDestination)); + MessageReceiverList.Add(new MessageReceiverRegistration(source, destination, callback, MessageReceiverRegistration.MatchType.SourceOrDestination)); } #endregion #region Device searching on iBus - const int findDeviceTimeout = 2000; + const int FindDeviceTimeout = 2000; - static ArrayList foundDevices = new ArrayList(); + static readonly ArrayList FoundDevices = new ArrayList(); public static bool FindDevice(DeviceAddress device) { - return FindDevice(device, findDeviceTimeout); + return FindDevice(device, FindDeviceTimeout); } public static bool FindDevice(DeviceAddress device, int timeout) { - if (foundDevices.Contains(device)) + if (FoundDevices.Contains(device)) { return true; } - lock (foundDevices) + lock (FoundDevices) { AfterMessageReceived += SaveFoundDevice; // TODO check broadcast poll request // device EnqueueMessage(new Message(DeviceAddress.Diagnostic, DeviceAddress.Broadcast, MessageRegistry.DataPollRequest)); Thread.Sleep(timeout); AfterMessageReceived -= SaveFoundDevice; - return foundDevices.Contains(device); + return FoundDevices.Contains(device); } } static void SaveFoundDevice(MessageEventArgs e) { - if (!foundDevices.Contains(e.Message.SourceDevice)) + if (!FoundDevices.Contains(e.Message.SourceDevice)) { - foundDevices.Add(e.Message.SourceDevice); + FoundDevices.Add(e.Message.SourceDevice); } } diff --git a/imBMW/iBus/Message.cs b/imBMW/iBus/Message.cs index 5377351..7e9058a 100644 --- a/imBMW/iBus/Message.cs +++ b/imBMW/iBus/Message.cs @@ -1,5 +1,4 @@ using System; -using System.Text; using imBMW.Tools; namespace imBMW.iBus @@ -9,18 +8,18 @@ public class Message public const int PacketLengthMin = 5; public const int PacketLengthMax = 64; - byte source; - byte destination; - byte[] data; - byte check; + byte _source; + byte _destination; + byte[] _data; + byte _check; - byte[] packet; - byte packetLength; - string packetDump; - string dataDump; - DeviceAddress sourceDevice = DeviceAddress.Unset; - DeviceAddress destinationDevice = DeviceAddress.Unset; - PerformanceInfo performanceInfo; + byte[] _packet; + byte _packetLength; + string _packetDump; + string _dataDump; + DeviceAddress _sourceDevice = DeviceAddress.Unset; + DeviceAddress _destinationDevice = DeviceAddress.Unset; + PerformanceInfo _performanceInfo; public Message(DeviceAddress source, DeviceAddress destination, params byte[] data) : this(source, destination, null, data) @@ -37,9 +36,9 @@ public Message(DeviceAddress source, DeviceAddress destination, string descripti { throw new ArgumentException("Wrong destination device"); } - init((byte)source, (byte)destination, data, description); - sourceDevice = source; - destinationDevice = destination; + Init((byte)source, (byte)destination, data, description); + _sourceDevice = source; + _destinationDevice = destination; } public Message(byte source, byte destination, params byte[] data) @@ -49,26 +48,26 @@ public Message(byte source, byte destination, params byte[] data) public Message(byte source, byte destination, string description, params byte[] data) { - init(source, destination, data, description); + Init(source, destination, data, description); } - void init(byte source, byte destination, byte[] data, string description = null) + void Init(byte source, byte destination, byte[] data, string description = null) { - this.source = source; - this.destination = destination; - this.data = data; - this.ReceiverDescription = description; - packetLength = (byte)(data.Length + 4); // + source + destination + len + chksum + _source = source; + _destination = destination; + _data = data; + ReceiverDescription = description; + _packetLength = (byte)(data.Length + 4); // + source + destination + len + chksum byte check = 0x00; check ^= source; - check ^= (byte)(packetLength - 2); + check ^= (byte)(_packetLength - 2); check ^= destination; foreach (byte b in data) { check ^= b; } - this.check = check; + _check = check; } public static Message TryCreate(byte[] packet) @@ -98,7 +97,7 @@ public static bool IsValid(byte[] packet, int length) return false; } - byte packetLength = (byte)(packet[1] + 2); + var packetLength = (byte)(packet[1] + 2); if (length < packetLength || packetLength < PacketLengthMin) { return false; @@ -119,7 +118,7 @@ public static bool CanStartWith(byte[] packet, int length) return true; } - byte packetLength = (byte)(packet[1] + 2); + var packetLength = (byte)(packet[1] + 2); if (packetLength < PacketLengthMin || packetLength > PacketLengthMax) { @@ -138,7 +137,7 @@ public byte PacketLength { get { - return packetLength; + return _packetLength; } } @@ -146,19 +145,19 @@ public byte[] Packet { get { - if (this.packet != null) + if (_packet != null) { - return this.packet; + return _packet; } - byte[] packet = new byte[PacketLength]; - packet[0] = source; + var packet = new byte[PacketLength]; + packet[0] = _source; packet[1] = (byte)(PacketLength - 2); - packet[2] = destination; - data.CopyTo(packet, 3); - packet[PacketLength - 1] = check; + packet[2] = _destination; + _data.CopyTo(packet, 3); + packet[PacketLength - 1] = _check; - this.packet = packet; + _packet = packet; return packet; } } @@ -167,49 +166,35 @@ public byte[] Data { get { - return data; + return _data; } } public String PacketDump { - get - { - if (packetDump == null) - { - packetDump = Packet.ToHex(' '); - } - return packetDump; - } + get { return _packetDump ?? (_packetDump = Packet.ToHex(' ')); } } public String DataDump { - get - { - if (dataDump == null) - { - dataDump = data.ToHex(' '); - } - return dataDump; - } + get { return _dataDump ?? (_dataDump = _data.ToHex(' ')); } } public DeviceAddress SourceDevice { get { - if (sourceDevice == DeviceAddress.Unset) + if (_sourceDevice == DeviceAddress.Unset) { try { - sourceDevice = (DeviceAddress)source; + _sourceDevice = (DeviceAddress)_source; } catch (InvalidCastException) { - sourceDevice = DeviceAddress.Unknown; + _sourceDevice = DeviceAddress.Unknown; } } - return sourceDevice; + return _sourceDevice; } } @@ -218,18 +203,18 @@ public DeviceAddress DestinationDevice { get { - if (destinationDevice == DeviceAddress.Unset) + if (_destinationDevice == DeviceAddress.Unset) { try { - destinationDevice = (DeviceAddress)destination; + _destinationDevice = (DeviceAddress)_destination; } catch (InvalidCastException) { - destinationDevice = DeviceAddress.Unknown; + _destinationDevice = DeviceAddress.Unknown; } } - return destinationDevice; + return _destinationDevice; } } @@ -240,14 +225,7 @@ public DeviceAddress DestinationDevice public PerformanceInfo PerformanceInfo { - get - { - if (performanceInfo == null) - { - performanceInfo = new PerformanceInfo(); - } - return performanceInfo; - } + get { return _performanceInfo ?? (_performanceInfo = new PerformanceInfo()); } } public override string ToString() diff --git a/imBMW/iBus/MessageRegistry.cs b/imBMW/iBus/MessageRegistry.cs index 4d971e0..63bc6d2 100644 --- a/imBMW/iBus/MessageRegistry.cs +++ b/imBMW/iBus/MessageRegistry.cs @@ -1,5 +1,3 @@ -using System; -using Microsoft.SPOT; using imBMW.Tools; using System.Collections; @@ -9,292 +7,290 @@ public static class MessageRegistry { #region Registries - static string[] messageTypeDescriptions = { - "", // "0x00", - "Device status request", - "Device status ready", - "Bus status request", - "Bus status", - "", // "0x05", - "DIAG read memory", - "DIAG write memory", - "DIAG read coding data", - "DIAG write coding data", - "", // "0x0A", - "", // "0x0B", - "Vehicle control", - "", // "0x0D", - "", // "0x0E", - "", // "0x0F", - "Ignition status request", - "Ignition status", - "IKE sensor status request", - "IKE sensor status", - "Country coding status request", - "Country coding status", - "Odometer request", - "Odometer", - "Speed/RPM", - "Temperature", - "IKE text display/Gong", - "IKE text status", - "Gong", - "Temperature request", - "", // "0x1E", - "UTC time and date", - "", // "0x20", - "Radio Short cuts", - "Text display confirmation", - "Display Text", - "Update ANZV", - "", // "0x25", - "", // "0x26", - "", // "0x27", - "", // "0x28", - "", // "0x29", - "On-Board Computer State Update", - "Phone LEDs", - "Phone symbol", // "0x2C", - "", // "0x2D", - "", // "0x2E", - "", // "0x2F", - "", // "0x30", - "Select screen item", // "0x31", - "MFL volume buttons", - "", // "0x33", - "DSP Equalizer Button", - "", // "0x35", - "", // "0x36", - "", // "0x37", - "CD status request", - "CD status", - "", // "0x3A", - "MFL media buttons", - "", // "0x3C", - "SDRS status request", - "SDRS status", - "", // "0x3F", - "Set On-Board Computer Data", - "On-Board Computer Data Request", - "", // "0x42", - "", // "0x43", - "", // "0x44", - "", // "0x45", - "LCD Clear", - "BMBT buttons", - "BMBT buttons", - "KNOB button", - "Monitor CD/Tape control", - "Monitor CD/Tape status", - "", // "0x4C", - "", // "0x4D", - "", // "0x4E", - "Monitor Control", - "", // "0x50", - "", // "0x51", - "", // "0x52", - "Vehicle data request", - "Vehicle data status", - "", // "0x55", - "", // "0x56", - "", // "0x57", - "", // "0x58", - "", // "0x59", - "Lamp status request", - "Lamp status", - "Instrument cluster lighting status", - "", // "0x5D", - "", // "0x5E", - "", // "0x5F", - "", // "0x60", - "", // "0x61", - "", // "0x62", - "", // "0x63", - "", // "0x64", - "", // "0x65", - "", // "0x66", - "", // "0x67", - "", // "0x68", - "", // "0x69", - "", // "0x6A", - "", // "0x6B", - "", // "0x6C", - "Sideview Mirror", // "0x6D", - "", // "0x6E", - "", // "0x6F", - "", // "0x70", - "Rain sensor status request", - "Remote Key buttons", - "", // "0x73", - "EWS key status", - "", // "0x75", - "External lights", // "0x76", - "", // "0x77", - "", // "0x78", - "Doors/windows status request", - "Doors/windows status", - "", // "0x7B", - "SHD status", - "", // "0x7D", - "", // "0x7E", - "", // "0x7F", - "", // "0x80", - "", // "0x81", - "", // "0x82", - "", // "0x83", - "", // "0x84", - "", // "0x85", - "", // "0x86", - "", // "0x87", - "", // "0x88", - "", // "0x89", - "", // "0x8A", - "", // "0x8B", - "", // "0x8C", - "", // "0x8D", - "", // "0x8E", - "", // "0x8F", - "", // "0x90", - "", // "0x91", - "", // "0x92", - "", // "0x93", - "", // "0x94", - "", // "0x95", - "", // "0x96", - "", // "0x97", - "", // "0x98", - "", // "0x99", - "", // "0x9A", - "", // "0x9B", - "", // "0x9C", - "", // "0x9D", - "", // "0x9E", - "", // "0x9F", - "DIAG data", - "", // "0xA1", - "Current position and time", - "", // "0xA3", - "Current location", - "Screen text", - "", // "0xA6", - "TMC status request", - "", // "0xA8", - "", // "0xA9", - "Navigation Control", - "", // "0xAB", - "", // "0xAC", - "", // "0xAD", - "", // "0xAE", - "", // "0xAF", - "", // "0xB0", - "", // "0xB1", - "", // "0xB2", - "", // "0xB3", - "", // "0xB4", - "", // "0xB5", - "", // "0xB6", - "", // "0xB7", - "", // "0xB8", - "", // "0xB9", - "", // "0xBA", - "", // "0xBB", - "", // "0xBC", - "", // "0xBD", - "", // "0xBE", - "", // "0xBF", - "", // "0xC0", - "", // "0xC1", - "", // "0xC2", - "", // "0xC3", - "", // "0xC4", - "", // "0xC5", - "", // "0xC6", - "", // "0xC7", - "", // "0xC8", - "", // "0xC9", - "", // "0xCA", - "", // "0xCB", - "", // "0xCC", - "", // "0xCD", - "", // "0xCE", - "", // "0xCF", - "", // "0xD0", - "", // "0xD1", - "", // "0xD2", - "", // "0xD3", - "RDS channel list", - "", // "0xD5", - "", // "0xD6", - "", // "0xD7", - "", // "0xD8", - "", // "0xD9", - "", // "0xDA", - "", // "0xDB", - "", // "0xDC", - "", // "0xDD", - "", // "0xDE", - "", // "0xDF", - "", // "0xE0", - "", // "0xE1", - "", // "0xE2", - "", // "0xE3", - "", // "0xE4", - "", // "0xE5", - "", // "0xE6", - "", // "0xE7", - "", // "0xE8", - "", // "0xE9", - "", // "0xEA", - "", // "0xEB", - "", // "0xEC", - "", // "0xED", - "", // "0xEE", - "", // "0xEF", - "", // "0xF0", - "", // "0xF1", - "", // "0xF2", - "", // "0xF3", - "", // "0xF4", - "", // "0xF5", - "", // "0xF6", - "", // "0xF7", - "", // "0xF8", - "", // "0xF9", - "", // "0xFA", - "", // "0xFB", - "", // "0xFC", - "", // "0xFD", - "", // "0xFE", - "", // "0xFF" - }; + static readonly string[] MessageTypeDescriptions = { + "", // "0x00", + "Device status request", + "Device status ready", + "Bus status request", + "Bus status", + "", // "0x05", + "DIAG read memory", + "DIAG write memory", + "DIAG read coding data", + "DIAG write coding data", + "", // "0x0A", + "", // "0x0B", + "Vehicle control", + "", // "0x0D", + "", // "0x0E", + "", // "0x0F", + "Ignition status request", + "Ignition status", + "IKE sensor status request", + "IKE sensor status", + "Country coding status request", + "Country coding status", + "Odometer request", + "Odometer", + "Speed/RPM", + "Temperature", + "IKE text display/Gong", + "IKE text status", + "Gong", + "Temperature request", + "", // "0x1E", + "UTC time and date", + "", // "0x20", + "Radio Short cuts", + "Text display confirmation", + "Display Text", + "Update ANZV", + "", // "0x25", + "", // "0x26", + "", // "0x27", + "", // "0x28", + "", // "0x29", + "On-Board Computer State Update", + "Phone LEDs", + "Phone symbol", + "", // "0x2D", + "", // "0x2E", + "", // "0x2F", + "", // "0x30", + "Select screen item", + "MFL volume buttons", + "", // "0x33", + "DSP Equalizer Button", + "", // "0x35", + "", // "0x36", + "RAD buttons", // "0x37", + "CD status request", + "CD status", + "", // "0x3A", + "MFL media buttons", + "", // "0x3C", + "SDRS status request", + "SDRS status", + "", // "0x3F", + "Set On-Board Computer Data", + "On-Board Computer Data Request", + "", // "0x42", + "", // "0x43", + "E46 IKE text", + "Radio status request", + "LCD Clear", + "BMBT buttons", + "BMBT buttons", + "KNOB button", + "Monitor CD/Tape control", + "Monitor CD/Tape status", + "", // "0x4C", + "", // "0x4D", + "Audio source selection", + "Monitor Control", + "", // "0x50", + "", // "0x51", + "", // "0x52", + "Vehicle data request", + "Vehicle data status", + "Service Interval Display", + "", // "0x56", + "", // "0x57", + "Headlight wipe interval", + "Light control status", + "Lamp status request", + "Lamp status", + "Instrument cluster lighting status", + "Light dimmer status request", + "", // "0x5E", + "", // "0x5F", + "", // "0x60", + "", // "0x61", + "", // "0x62", + "", // "0x63", + "", // "0x64", + "", // "0x65", + "", // "0x66", + "", // "0x67", + "", // "0x68", + "", // "0x69", + "", // "0x6A", + "", // "0x6B", + "", // "0x6C", + "Sideview Mirror", + "", // "0x6E", + "", // "0x6F", + "Remote control central locking status", + "Rain sensor status request", + "Remote Key buttons", + "EWS status request", + "EWS key status", + "Wiper status request", + "External lights", + "Wiper status", + "Seat Memory", + "Doors/windows status request", + "Doors/windows status", + "", // "0x7B", + "SHD status", + "SHD control", + "", // "0x7E", + "", // "0x7F", + "", // "0x80", + "", // "0x81", + "", // "0x82", + "Air conditioning compressor status", + "", // "0x84", + "", // "0x85", + "", // "0x86", + "", // "0x87", + "", // "0x88", + "", // "0x89", + "", // "0x8A", + "", // "0x8B", + "", // "0x8C", + "", // "0x8D", + "", // "0x8E", + "", // "0x8F", + "", // "0x90", + "", // "0x91", + "", // "0x92", + "", // "0x93", + "", // "0x94", + "", // "0x95", + "", // "0x96", + "", // "0x97", + "", // "0x98", + "", // "0x99", + "", // "0x9A", + "", // "0x9B", + "", // "0x9C", + "", // "0x9D", + "", // "0x9E", + "", // "0x9F", + "DIAG data", + "", // "0xA1", + "Current position and time", + "", // "0xA3", + "Current location", + "Screen text", + "Special indicators", + "TMC status request", + "TMC data", + "Telephone data", + "Navigation Control", + "Remote control status", + "", // "0xAC", + "", // "0xAD", + "", // "0xAE", + "", // "0xAF", + "", // "0xB0", + "", // "0xB1", + "", // "0xB2", + "", // "0xB3", + "", // "0xB4", + "", // "0xB5", + "", // "0xB6", + "", // "0xB7", + "", // "0xB8", + "", // "0xB9", + "", // "0xBA", + "", // "0xBB", + "", // "0xBC", + "", // "0xBD", + "", // "0xBE", + "", // "0xBF", + "", // "0xC0", + "", // "0xC1", + "", // "0xC2", + "", // "0xC3", + "", // "0xC4", + "", // "0xC5", + "", // "0xC6", + "", // "0xC7", + "", // "0xC8", + "", // "0xC9", + "", // "0xCA", + "", // "0xCB", + "", // "0xCC", + "", // "0xCD", + "", // "0xCE", + "", // "0xCF", + "", // "0xD0", + "", // "0xD1", + "", // "0xD2", + "", // "0xD3", + "RDS channel list", + "", // "0xD5", + "", // "0xD6", + "", // "0xD7", + "", // "0xD8", + "", // "0xD9", + "", // "0xDA", + "", // "0xDB", + "", // "0xDC", + "", // "0xDD", + "", // "0xDE", + "", // "0xDF", + "", // "0xE0", + "", // "0xE1", + "", // "0xE2", + "", // "0xE3", + "", // "0xE4", + "", // "0xE5", + "", // "0xE6", + "", // "0xE7", + "", // "0xE8", + "", // "0xE9", + "", // "0xEA", + "", // "0xEB", + "", // "0xEC", + "", // "0xED", + "", // "0xEE", + "", // "0xEF", + "", // "0xF0", + "", // "0xF1", + "", // "0xF2", + "", // "0xF3", + "", // "0xF4", + "", // "0xF5", + "", // "0xF6", + "", // "0xF7", + "", // "0xF8", + "", // "0xF9", + "", // "0xFA", + "", // "0xFB", + "", // "0xFC", + "", // "0xFD", + "", // "0xFE", + "" // "0xFF" + }; - public static byte[] DataPollRequest = new byte[] { 0x01 }; - public static byte[] DataPollResponse = new byte[] { 0x02, 0x00 }; - public static byte[] DataAnnounce = new byte[] { 0x02, 0x01 }; + public static byte[] DataPollRequest = { 0x01 }; + public static byte[] DataPollResponse = { 0x02, 0x00 }; + public static byte[] DataAnnounce = { 0x02, 0x01 }; - static Hashtable messageDescriptions; + static readonly Hashtable MessageDescriptions; static MessageRegistry() { - messageDescriptions = new Hashtable(); - messageDescriptions.Add(DataPollRequest.ToHex(' '), "Poll request"); - messageDescriptions.Add(DataPollResponse.ToHex(' '), "Poll response"); - messageDescriptions.Add(DataAnnounce.ToHex(' '), "Announce"); + MessageDescriptions = new Hashtable + { + {DataPollRequest.ToHex(' '), "Poll request"}, + {DataPollResponse.ToHex(' '), "Poll response"}, + {DataAnnounce.ToHex(' '), "Announce"} + }; } #endregion public static string ToPrettyString(this Message message, bool withPerformanceInfo = false) { - string description = message.Describe(); - if (description == null) - { - description = message.DataDump; - } + string description = message.Describe() ?? message.DataDump; description = message.SourceDevice.ToStringValue() + " > " + message.DestinationDevice.ToStringValue() + ": " + description; if (withPerformanceInfo) { - description += " (" + message.PerformanceInfo.ToString() + ")"; + description += " (" + message.PerformanceInfo + ")"; } return description; } @@ -311,17 +307,17 @@ public static string Describe(this Message message) return message.ReceiverDescription; } - if (messageDescriptions.Contains(message.DataDump)) + if (MessageDescriptions.Contains(message.DataDump)) { - return (string)messageDescriptions[message.DataDump]; + return (string)MessageDescriptions[message.DataDump]; } byte firstByte = message.Data[0]; - if (firstByte >= messageTypeDescriptions.Length || messageTypeDescriptions[firstByte] == "") + if (firstByte >= MessageTypeDescriptions.Length || MessageTypeDescriptions[firstByte] == "") { return null; } - return message.DataDump + " (" + messageTypeDescriptions[firstByte] + ')'; + return message.DataDump + " (" + MessageTypeDescriptions[firstByte] + ')'; } } } diff --git a/imBMW/imBMW.csproj b/imBMW/imBMW.csproj index 8e49f9d..3720cc0 100644 --- a/imBMW/imBMW.csproj +++ b/imBMW/imBMW.csproj @@ -35,6 +35,7 @@ + @@ -56,9 +57,12 @@ + + + @@ -90,7 +94,10 @@ + + + From e129d98351e4771639971cbe48ee03d8992a223c Mon Sep 17 00:00:00 2001 From: arctus Date: Mon, 19 May 2014 22:08:01 +0300 Subject: [PATCH 2/2] Revert back changes to original distribution --- Devices/V2/Program.cs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Devices/V2/Program.cs b/Devices/V2/Program.cs index 7a40027..238cd8a 100644 --- a/Devices/V2/Program.cs +++ b/Devices/V2/Program.cs @@ -63,7 +63,7 @@ static void Init() SettingsScreen.Instance.Status = version; Logger.Info(version); - //var sd = GetRootDirectory(); + var sd = GetRootDirectory(); // todo get config @@ -152,23 +152,22 @@ static void Init() // Enable comfort features //Features.Comfort.AllFeaturesEnabled = true; - Comfort.AutoLockDoors = false; + Comfort.AutoLockDoors = true; Comfort.AutoUnlockDoors = true; Comfort.AutoCloseWindows = true; Logger.Info("Comfort features inited"); - var rcSwitch = new RCSwitch(Pin.PC0); - Gates.Init(rcSwitch); - Gates.AddGatesObserver(54.708527777777782f, 25.289972222222225f, 0.1f, GateToggleMethod.Send433MhzSignal, new[] { "477D33", "477D3C" }); + //var rcSwitch = new RCSwitch(Pin.PC0); + //Gates.Init(rcSwitch); + //Gates.AddGatesObserver(54.708527777777782f, 25.289972222222225f, 0.1f, GateToggleMethod.Send433MhzSignal, new[] { "477D33", "477D3C" }); // Set iPod or Bluetooth as AUX or CDC-emulator - _player = new BluetoothOVC3860(Serial.COM2); - //sd != null ? sd + @"\contacts.vcf" : null); + _player = new BluetoothOVC3860(Serial.COM2, sd != null ? sd + @"\contacts.vcf" : null); //player = new iPodViaHeadset(Pin.PC2); Radio.Init(); Logger.Info("Radio inited"); - //if (Manager.FindDevice(DeviceAddress.OnBoardMonitor)) + if (Manager.FindDevice(DeviceAddress.OnBoardMonitor)) { MediaEmulator emulator; emulator = new BordmonitorAUX(_player); @@ -178,12 +177,12 @@ static void Init() BordmonitorMenu.Init(emulator); Logger.Info("BordmonitorAUX inited"); } - //else - //{ - // // TODO implement radio menu - // //iBus.Devices.Emulators.CDChanger.Init(player); - // Logger.Info("CDChanger emulator inited"); - //} + else + { + // TODO implement radio menu + //iBus.Devices.Emulators.CDChanger.Init(player); + Logger.Info("CDChanger emulator inited"); + } ShieldLED = new OutputPort(Pin.PA7, false); _player.IsPlayingChanged += (p, s) => {