예제 #1
0
        /// <summary>
        /// Set the amount of time that we'll wait for a message to arrive.
        /// </summary>
        public override async Task SetTimeout(TimeoutScenario scenario)
        {
            if (this.currentTimeout == scenario)
            {
                return;
            }

            int milliseconds = this.GetVpwTimeoutMilliseconds(scenario);

            // Adding some more just in case...
            milliseconds += 20;

            this.Logger.AddDebugMessage("Setting timeout for " + scenario + ", " + milliseconds.ToString() + " ms.");

            // The port timeout needs to be considerably longer than the device timeout,
            // otherwise you get "STOPPED" or "NO DATA" somewhat randomly. (I mostly saw
            // this when sending the tool-present messages, but that might be coincidence.)
            //
            // 100 was not enough
            // 150 seems like enough
            // Consider 200 if STOPPED / NO DATA is still a problem.
            this.Port.SetTimeout(milliseconds + 150);

            // I briefly tried hard-coding timeout values for the AT ST command,
            // but that's a recipe for failure. If the port timeout is shorter
            // than the device timeout, reads will consistently fail.
            int    parameter = Math.Min(Math.Max(1, (milliseconds / 4)), 99);
            string value     = parameter.ToString("00");

            await this.SendAndVerify("AT ST " + value, "OK");
        }
예제 #2
0
        /// <summary>
        /// Not yet implemented.
        /// </summary>
        public override Task <TimeoutScenario> SetTimeout(TimeoutScenario scenario)
        {
            TimeoutScenario previousScenario = this.currentTimeoutScenario;

            this.currentTimeoutScenario = scenario;
            return(Task.FromResult(previousScenario));
        }
예제 #3
0
        /// <summary>
        /// Send a tool-present message.
        /// </summary>
        private async Task SendNotification()
        {
            this.logger.AddDebugMessage("Sending 'test device present' notification.");
            Message         message          = this.protocol.CreateTestDevicePresentNotification();
            TimeoutScenario originalScenario = await this.device.SetTimeout(TimeoutScenario.Minimum);

            await this.device.SendMessage(message);

            await this.device.SetTimeout(originalScenario);
        }
예제 #4
0
        /// <summary>
        /// Estimate timeouts. The code above seems to do a pretty good job, but this is easier to experiment with.
        /// </summary>
        protected int __GetVpwTimeoutMilliseconds(TimeoutScenario scenario)
        {
            switch (scenario)
            {
            case TimeoutScenario.ReadProperty:
                return(100);

            case TimeoutScenario.ReadMemoryBlock:
                return(2500);

            case TimeoutScenario.SendKernel:
                return(1000);

            default:
                throw new NotImplementedException("Unknown timeout scenario " + scenario);
            }
        }
예제 #5
0
        /// <summary>
        /// Calculates the time required for the given scenario at the current VPW speed.
        /// </summary>
        protected int GetVpwTimeoutMilliseconds(TimeoutScenario scenario)
        {
            int packetSize;

            switch (scenario)
            {
            case TimeoutScenario.ReadProperty:
                // Approximate number of bytes in a get-VIN or get-OSID response.
                packetSize = 50;
                break;

            case TimeoutScenario.ReadCrc:
                // These packets are actually only 15 bytes, but the ReadProperty timeout wasn't
                // enough for the AllPro at 4x. Still not sure why. So this is a bit of a hack.
                // TODO: Figure out why the AllPro needs a hack to receive CRC values at 4x.
                packetSize = 1000;
                break;

            case TimeoutScenario.ReadMemoryBlock:
                // Adding 20 bytes to account for the 'read request accepted'
                // message that comes before the read payload.
                packetSize = 20 + this.MaxReceiveSize;

                // Not sure why this is necessary, but AllPro 2k reads won't work without it.
                //packetSize = (int) (packetSize * 1.1);
                packetSize = (int)(packetSize * 2.5);
                break;

            case TimeoutScenario.SendKernel:
                packetSize = this.MaxSendSize + 20;
                break;

            case TimeoutScenario.Maximum:
                return(0xFF * 4);

            default:
                throw new NotImplementedException("Unknown timeout scenario " + scenario);
            }

            int    bitsPerByte   = 9; // 8N1 serial
            double bitsPerSecond = this.speed == VpwSpeed.Standard ? 10.4 : 41.6;
            double milliseconds  = (packetSize * bitsPerByte) / bitsPerSecond;

            // Add 10% just in case.
            return((int)(milliseconds * 1.1));
        }
예제 #6
0
        /// <summary>
        /// Set the amount of time that we'll wait for a message to arrive.
        /// </summary>
        public override async Task <TimeoutScenario> SetTimeout(TimeoutScenario scenario)
        {
            if (this.currentTimeoutScenario == scenario)
            {
                return(this.currentTimeoutScenario);
            }

            int milliseconds = this.implementation.GetTimeoutMilliseconds(scenario, this.Speed);

            this.Logger.AddDebugMessage("Setting timeout for " + scenario + ", " + milliseconds.ToString() + " ms.");

            // The port timeout needs to be considerably longer than the device timeout,
            // otherwise you get "STOPPED" or "NO DATA" somewhat randomly. (I mostly saw
            // this when sending the tool-present messages, but that might be coincidence.)
            //
            // Consider increasing if STOPPED / NO DATA is still a problem.
            this.Port.SetTimeout(milliseconds + 1000);

            // This code is so problematic that I've left it here as a warning. The app is
            // unable to receive the response to the erase command if this code is enabled.
            //
            //if (this.implementation is ScanToolDeviceImplementation)
            //{
            //    TimeoutScenario old = this.currentTimeoutScenario;
            //    this.currentTimeoutScenario = scenario;
            //    return old;
            //}

            // I briefly tried hard-coding timeout values for the AT ST command,
            // but that's a recipe for failure. If the port timeout is shorter
            // than the device timeout, reads will consistently fail.
            int    parameter = Math.Min(Math.Max(1, (milliseconds / 4)), 255);
            string value     = parameter.ToString("X2");

            await this.implementation.SendAndVerify("AT ST " + value, "OK");

            TimeoutScenario result = this.currentTimeoutScenario;

            this.currentTimeoutScenario         = scenario;
            this.implementation.TimeoutScenario = scenario;
            return(result);
        }
예제 #7
0
        /// <summary>
        /// Calculates the time required for the given scenario at the current VPW speed.
        /// </summary>
        protected int GetVpwTimeoutMilliseconds(TimeoutScenario scenario)
        {
            int packetSize;

            switch (scenario)
            {
            case TimeoutScenario.ReadProperty:
                // Approximate number of bytes in a get-VIN or get-OSID response.
                packetSize = 20;
                break;

            case TimeoutScenario.ReadMemoryBlock:
                // Adding 20 bytes to account for the 'read request accepted'
                // message that comes before the read payload.
                packetSize = 20 + this.MaxReceiveSize;

                // Not sure why this is necessary, but AllPro 2k reads won't work without it.
                //packetSize = (int) (packetSize * 1.1);
                packetSize = (int)(packetSize * 2.2);
                break;

            case TimeoutScenario.SendKernel:
                packetSize = this.MaxSendSize + 20;
                break;

            default:
                throw new NotImplementedException("Unknown timeout scenario " + scenario);
            }

            int    bitsPerByte   = 9; // 8N1 serial
            double bitsPerSecond = this.speed == VpwSpeed.Standard ? 10.4 : 41.6;
            double milliseconds  = (packetSize * bitsPerByte) / bitsPerSecond;

            // Add 10% just in case.
            return((int)(milliseconds * 1.1));
        }
예제 #8
0
 /// <summary>
 /// Not needed.
 /// </summary>
 public override Task SetTimeout(TimeoutScenario scenario)
 {
     return(Task.FromResult(0));
 }
예제 #9
0
 /// <summary>
 /// Set the timeout period to wait for responses to incoming messages.
 /// </summary>
 public abstract Task SetTimeout(TimeoutScenario scenario);
예제 #10
0
        /// <summary>
        /// Does everything required to switch to VPW 4x
        /// </summary>
        public async Task <bool> VehicleSetVPW4x(VpwSpeed newSpeed, ToolPresentNotifier notifier)
        {
            if (!device.Supports4X)
            {
                if (newSpeed == VpwSpeed.FourX)
                {
                    // where there is no support only report no switch to 4x
                    logger.AddUserMessage("This interface does not support VPW 4x");
                }
                return(true);
            }

            // Configure the vehicle bus when switching to 4x
            if (newSpeed == VpwSpeed.FourX)
            {
                logger.AddUserMessage("Attempting switch to VPW 4x");
                await device.SetTimeout(TimeoutScenario.ReadProperty);

                // The list of modules may not be useful after all, but
                // checking for an empty list indicates an uncooperative
                // module on the VPW bus.
                List <byte> modules = await this.RequestHighSpeedPermission(notifier);

                if (modules == null)
                {
                    // A device has refused the switch to high speed mode.
                    return(false);
                }

                Message broadcast = this.protocol.CreateBeginHighSpeed(DeviceId.Broadcast);
                await this.device.SendMessage(broadcast);

                // Check for any devices that refused to switch to 4X speed.
                // These responses usually get lost, so this code might be pointless.
                Message response = null;
                while ((response = await this.device.ReceiveMessage()) != null)
                {
                    Response <bool> refused = this.protocol.ParseHighSpeedRefusal(response);
                    if (refused.Status != ResponseStatus.Success)
                    {
                        // This should help ELM devices receive responses.
                        await notifier.ForceNotify();

                        continue;
                    }

                    if (refused.Value == false)
                    {
                        // TODO: Add module number.
                        this.logger.AddUserMessage("Module refused high-speed switch.");
                        return(false);
                    }
                }
            }
            else
            {
                logger.AddUserMessage("Reverting to VPW 1x");
            }

            // Request the device to change
            await device.SetVpwSpeed(newSpeed);

            TimeoutScenario scenario = newSpeed == VpwSpeed.Standard ? TimeoutScenario.ReadProperty : TimeoutScenario.ReadMemoryBlock;
            await device.SetTimeout(scenario);

            return(true);
        }
예제 #11
0
 /// <summary>
 /// Not yet implemented.
 /// </summary>
 public override Task <TimeoutScenario> SetTimeout(TimeoutScenario scenario)
 {
     return(Task.FromResult(this.currentTimeoutScenario));
 }
예제 #12
0
 /// <summary>
 /// Change the device's timeout.
 /// </summary>
 public async Task <TimeoutScenario> SetDeviceTimeout(TimeoutScenario scenario)
 {
     return(await this.device.SetTimeout(scenario));
 }
 /// <summary>
 /// Get the time required for the given scenario.
 /// </summary>
 public virtual int GetTimeoutMilliseconds(TimeoutScenario scenario, VpwSpeed speed)
 {
     // This base class is only instantiated for device-independent initialization.
     return(250);
 }
예제 #14
0
 /// <summary>
 /// Change the device's timeout.
 /// </summary>
 public async Task SetDeviceTimeout(TimeoutScenario scenario)
 {
     await this.device.SetTimeout(scenario);
 }
예제 #15
0
        /// <summary>
        /// Get the time required for the given scenario.
        /// </summary>
        public override int GetTimeoutMilliseconds(TimeoutScenario scenario, VpwSpeed speed)
        {
            int milliseconds;

            if (speed == VpwSpeed.Standard)
            {
                switch (scenario)
                {
                case TimeoutScenario.Minimum:
                    milliseconds = 0;
                    break;

                case TimeoutScenario.ReadProperty:
                    milliseconds = 25;
                    break;

                case TimeoutScenario.ReadCrc:
                    milliseconds = 100;
                    break;

                case TimeoutScenario.ReadMemoryBlock:
                    milliseconds = 250;
                    break;

                case TimeoutScenario.EraseMemoryBlock:
                    milliseconds = 1000;
                    break;

                case TimeoutScenario.WriteMemoryBlock:
                    milliseconds = 200;
                    break;

                case TimeoutScenario.SendKernel:
                    milliseconds = 500;
                    break;

                case TimeoutScenario.DataLogging1:
                    milliseconds = 25;
                    break;

                case TimeoutScenario.DataLogging2:
                    milliseconds = 40;
                    break;

                case TimeoutScenario.DataLogging3:
                    milliseconds = 60;
                    break;

                case TimeoutScenario.Maximum:
                    return(1020);

                default:
                    throw new NotImplementedException("Unknown timeout scenario " + scenario);
                }
            }
            else
            {
                switch (scenario)
                {
                case TimeoutScenario.Minimum:
                    milliseconds = 0;
                    break;

                // The app doesn't currently do this in 4X mode, so this is only a guess.
                case TimeoutScenario.ReadProperty:
                    milliseconds = 12;
                    break;

                case TimeoutScenario.ReadCrc:
                    milliseconds = 100;
                    break;

                case TimeoutScenario.ReadMemoryBlock:
                    milliseconds = 50;
                    break;

                case TimeoutScenario.EraseMemoryBlock:
                    milliseconds = 1000;
                    break;

                case TimeoutScenario.WriteMemoryBlock:
                    milliseconds = 170;
                    break;

                case TimeoutScenario.SendKernel:
                    milliseconds = 10;
                    break;

                case TimeoutScenario.DataLogging1:
                    milliseconds = 7;
                    break;

                case TimeoutScenario.DataLogging2:
                    milliseconds = 10;
                    break;

                case TimeoutScenario.DataLogging3:
                    milliseconds = 15;
                    break;

                case TimeoutScenario.Maximum:
                    return(1020);

                default:
                    throw new NotImplementedException("Unknown timeout scenario " + scenario);
                }
            }

            return(milliseconds);
        }
        /// <summary>
        /// Get the time required for the given scenario.
        /// </summary>
        public override int GetTimeoutMilliseconds(TimeoutScenario scenario, VpwSpeed speed)
        {
            int milliseconds;

            if (speed == VpwSpeed.Standard)
            {
                switch (scenario)
                {
                case TimeoutScenario.Minimum:
                    milliseconds = 0;
                    break;

                case TimeoutScenario.ReadProperty:
                    milliseconds = 25;
                    break;

                case TimeoutScenario.ReadCrc:
                    milliseconds = 100;
                    break;

                case TimeoutScenario.ReadMemoryBlock:
                    milliseconds = 110;
                    break;

                case TimeoutScenario.EraseMemoryBlock:
                    milliseconds = 1000;
                    break;

                case TimeoutScenario.WriteMemoryBlock:
                    milliseconds = 800;     // 125 works, added some for safety
                    break;

                case TimeoutScenario.SendKernel:
                    milliseconds = 500;
                    break;

                case TimeoutScenario.DataLogging1:
                    milliseconds = 25;
                    break;

                case TimeoutScenario.DataLogging2:
                    milliseconds = 40;
                    break;

                case TimeoutScenario.DataLogging3:
                    milliseconds = 60;
                    break;

                case TimeoutScenario.Maximum:
                    return(1020);

                default:
                    throw new NotImplementedException("Unknown timeout scenario " + scenario);
                }
            }
            else
            {
                throw new NotImplementedException("Since when did ScanTool devices support 4x?");
            }

            return(milliseconds);
        }