Search code examples
motorolahandheldcradle

How to Programmatically Determine that a Motorola MC55 MC65 MC67 Is in the Cradle


We need to be able to determine within the application running on the handheld device that the device has been returned to the cradle.

While one method might be to observe if the battery charge level increases, this approach is really a workaround and will fail if the battery is at 100% charge.

We've unsuccessfully searched the EMD help files.


Solution

  • The approach i take is to P/Invoke and check the PowerStatus of the device so i created a class called PowerStatus:

    public enum ACLineStatus { Offline = 0, Online = 1, Unknown = 255 }
    [Flags]
    public enum BatteryStatus { High = 1, Low = 2, Critical = 4, Charging = 8, NoSystemBattery = 128, Unknown =-1 }
    
    public class PowerStatus
    {
        private struct _SYSTEM_POWER_STATUS_EX
        {
            public byte ACLineStatus;
            public byte BatteryFlag;
            public byte BatteryLifePercent;
            public byte Reserved1;
            public uint BatteryLifeTime;
            public uint BatteryFullLifeTime;
            public byte Reserved2;
            public byte BackupBatteryFlag;
            public byte BackupBatteryLifePercent;
            public byte Reserved3;
            public uint BackupBatteryLifeTime;
            public uint BackupBatteryFullLifeTime;
        }
    
        [DllImport("coredll")]
        private static extern uint GetSystemPowerStatusEx(ref _SYSTEM_POWER_STATUS_EX lpSystemPowerStatus,
            bool fUpdate);
    
        public ACLineStatus ACLineStatus { get; set; }
        public BatteryStatus BatteryStatus { get; set; }
        public byte? BatteryLifePercent { get; set; }
        public TimeSpan? BatteryLifeTime { get; set; }
        public TimeSpan? BatteryFullLifeTime { get; set; }
        public BatteryStatus BackupBatteryStatus { get; set; }
        public byte? BackupBatteryLifePercent { get; set; }
        public TimeSpan? BackupBatteryLifeTime { get; set; }
        public TimeSpan? BackupBatteryFullLifeTime { get; set; }
    
        private PowerStatus()
        {
    
        }
    
        public static PowerStatus GetCurrent()
        {
            _SYSTEM_POWER_STATUS_EX powerStatus = new _SYSTEM_POWER_STATUS_EX();
            GetSystemPowerStatusEx(ref powerStatus, true);
    
            return new PowerStatus
            {
                ACLineStatus = (ACLineStatus)powerStatus.ACLineStatus,
                BatteryStatus = (BatteryStatus)powerStatus.BatteryFlag,
                BatteryLifePercent = powerStatus.BatteryLifePercent.Between((byte)0, (byte)100) ? (byte?)powerStatus.BatteryLifePercent : null,
                BatteryLifeTime = powerStatus.BatteryLifeTime >= 0 ? new TimeSpan(0, 0, (int)powerStatus.BatteryLifeTime) as TimeSpan? : null,
                BatteryFullLifeTime = powerStatus.BatteryFullLifeTime >= 0 ? new TimeSpan(0, 0, (int)powerStatus.BatteryFullLifeTime) as TimeSpan? : null,
                BackupBatteryStatus = (BatteryStatus)powerStatus.BackupBatteryFlag,
                BackupBatteryLifePercent = powerStatus.BackupBatteryLifePercent.Between((byte)0, (byte)100) ? (byte?)powerStatus.BackupBatteryLifePercent : null,
                BackupBatteryLifeTime = powerStatus.BackupBatteryLifeTime >= 0 ? new TimeSpan(0, 0, (int)powerStatus.BackupBatteryLifeTime) as TimeSpan? : null,
                BackupBatteryFullLifeTime = powerStatus.BackupBatteryFullLifeTime >= 0 ? new TimeSpan(0, 0, (int)powerStatus.BackupBatteryFullLifeTime) as TimeSpan? : null
            };
        }
    }
    

    and then in my "device" class i have a timer which fires an event when the device is docked

    public static event EventHandler DeviceDocked;
    
        private static ACLineStatus _lastPowerState = PowerStatus.GetCurrent().ACLineStatus;
        private static void timer_Tick(object state)
        {
            ACLineStatus powerState = PowerStatus.GetCurrent().ACLineStatus;
            _timer.Change(Timeout.Infinite, Timeout.Infinite);
            if (powerState == ACLineStatus.Online && _lastPowerState == ACLineStatus.Offline)
            {
                var e = DeviceDocked;
                if (e != null)
                {
                    e(null, EventArgs.Empty);
                }
            }
            _lastPowerState = powerState;
            _timer.Change(1000, Timeout.Infinite);
        }
    

    That PowerStatus.GetCurrent() is probably all you need.. i hope this helps :)