예제 #1
0
        /// <summary>
        /// Parse data for specified pid
        /// </summary>
        /// <param name="odbPid"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private Double parseDataForSpecifiedPid(OdbPid odbPid, OdbData data)
        {
            int A = -1, B = -1, C = -1, D = -1;
            int length = data.Data.Length;

            if (length > 4 || length == 0)
            {
                throw new OdbException(OdbError.IncorrectDataLength);
            }

            if (length >= 4)
            {
                D = Convert.ToInt32(data.Data[3], 16);
            }
            if (length >= 3)
            {
                C = Convert.ToInt32(data.Data[2], 16);
            }
            if (length >= 2)
            {
                B = Convert.ToInt32(data.Data[1], 16);
            }
            if (length >= 1)
            {
                A = Convert.ToInt32(data.Data[0], 16);
            }

            return(odbPid.Compute(A, B, C, D));
        }
예제 #2
0
        /// <summary>
        /// Receive data from device
        /// </summary>
        /// <param name="what"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        private async Task <OdbResponse> receiveDataFromDevice(OdbPid what, DateTime start)
        {
            //await for response
            await Task.Delay(this.getReponseByPid(what));

            //create response
            OdbResponse odbResponse = new OdbResponse();

            odbResponse.Pid = what;

            try
            {
                //reader
                uint loaded = await reader.LoadAsync(BUFFER_STEP);

                String response = reader.ReadString(reader.UnconsumedBufferLength);
                while (loaded == BUFFER_STEP)
                {
                    loaded = await reader.LoadAsync(BUFFER_STEP);

                    response += reader.ReadString(reader.UnconsumedBufferLength);
                }
                odbResponse.Response = this.clearResponse(response, what);
                odbResponse.IsValid  = this.isValidResponse(response, what);
            }
            catch
            {
                odbResponse.Response = "";
                odbResponse.IsValid  = false;
            }

            odbResponse.Time = DateTime.Now.Subtract(start);

            return(odbResponse);
        }
예제 #3
0
        /// <summary>
        /// Get data for pid
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public OdbQueryResponse RequestFor(OdbPid pid)
        {
            //add new query to databaze
            if (!queryResponses.ContainsKey(pid))
            {
                OdbQuery newQuery = new OdbQuery();
                newQuery.Pid    = pid;
                newQuery.Status = this.checkSupported(newQuery);
                queryResponses.Add(pid, newQuery);

                reporter.ReportNewQuery(newQuery);
            }

            //read data from query
            OdbQuery         query    = queryResponses[pid];
            OdbQueryResponse response = new OdbQueryResponse();

            if (query.Status == QueryStatus.Complete)
            {
                response.Data     = query.Data;
                response.Unit     = query.Pid.Units;
                response.MinValue = query.Pid.MinValue;
                response.MaxValue = query.Pid.MaxValue;

                return(response);
            }
            return(null);
        }
예제 #4
0
 /// <summary>
 /// Get response time what for pid
 /// </summary>
 /// <param name="what"></param>
 /// <returns></returns>
 private int getReponseByPid(OdbPid what)
 {
     if (what.IsElmCommand)
     {
         return(500);
     }
     return(250);
 }
예제 #5
0
 /// <summary>
 /// Clear line
 /// </summary>
 /// <param name="what"></param>
 /// <param name="line"></param>
 /// <returns></returns>
 private string clearLine(OdbPid what, String line)
 {
     line = line.Replace("\n", " ");
     line = line.Replace(">", "");
     line = line.Replace(what.Pid, "");
     line = line.Trim();
     return(line);
 }
예제 #6
0
 /// <summary>
 /// Get data for pid
 /// </summary>
 /// <param name="pid"></param>
 /// <returns></returns>
 public void UnregisterQuery(OdbPid pid)
 {
     //remove query from databaze
     if (queryResponses.ContainsKey(pid))
     {
         queryResponses.Remove(pid);
         reporter.ReportDeleteQuery(pid);
     }
 }
예제 #7
0
        /// <summary>
        /// Send message and check response
        /// </summary>
        /// <param name="what"></param>
        /// <returns></returns>
        public async Task <OdbResponse> SendAndCheck(OdbPid what)
        {
            OdbResponse response = await this.Send(what);

            if (!response.Response.Contains(what.ExpectedResponse))
            {
                throw new OdbException(OdbError.WrongResponseFromDevice);
            }
            return(response);
        }
예제 #8
0
        /// <summary>
        /// Get supp
        /// </summary>
        /// <param name="what"></param>
        /// <returns></returns>
        private async Task registerSupportedPid(OdbPid what)
        {
            OdbResponse response = await this.socket.SendAndCheck(what);

            OdbData data = this.socket.ResolveData(response, what);

            if (data != null)
            {
                this.decodeSupportedPidsAndRegisterIt(what, data);
            }
        }
예제 #9
0
        /// <summary>
        /// Clear response message
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private string clearResponse(string response, OdbPid what)
        {
            response = response.Replace("\r", " ");

            String[] lines = response.Split('\n');
            for (int i = lines.Length - 1; i >= 0; i--)
            {
                String line = lines[i];
                line = this.clearLine(what, line);

                if (line.Length > 0)
                {
                    return(line);
                }
            }
            return(this.clearLine(what, lines.Last()));
        }
예제 #10
0
 /// <summary>
 /// Check if pid is supported for ecu
 /// </summary>
 /// <param name="ecu"></param>
 /// <param name="pid"></param>
 /// <returns></returns>
 public Boolean IsPidSupportedForEcu(Ecu ecu, OdbPid pid)
 {
     if (supportedPids.ContainsKey(ecu.EcuId))
     {
         var modes = supportedPids[ecu.EcuId];
         if (modes.ContainsKey(OdbPids.ATSP0))
         {
             var pids = modes[OdbPids.ATSP0];
             return(pids.Contains(pid.GetPidIdInDecimal()));
         }
         if (modes.ContainsKey(pid.Mode))
         {
             var pids = modes[pid.Mode];
             return(pids.Contains(pid.GetPidIdInDecimal()));
         }
     }
     return(false);
 }
예제 #11
0
        /// <summary>
        /// Load supported PIds
        /// </summary>
        /// <returns></returns>
        private async Task LoadSupportedProtocols(OdbProtocol protocolType = OdbProtocol.Unknown, int protocolNumber = 0)
        {
            var selectedProtocol = -1;

            if (protocolType == OdbProtocol.Unknown)
            {
                OdbPid protocol = null;
                for (selectedProtocol = 0; selectedProtocol <= 9; selectedProtocol++)
                {
                    protocol = OdbPids.GetPidForProtocolNumber(selectedProtocol);
                    try
                    {
                        OdbResponse response = await this.socket.SendAndCheck(protocol);

                        if (response.IsValid)
                        {
                            break;
                        }
                    }
                    catch
                    {
                        reporter.ReportInfo("Protocol ATSP" + protocol.Description + " is not supported.");
                    }
                }

                if (selectedProtocol == 10)
                {
                    throw new OdbException(OdbError.CouldNotFindCompatibleProtocol);
                }

                this.socket.SelectedProtocol = protocol;
            }
            else if (protocolType == OdbProtocol.Specified && protocolNumber > 0 && protocolNumber < 10)
            {
                OdbPid protocol = OdbPids.GetPidForProtocolNumber(selectedProtocol);
                await this.socket.SendAndCheck(protocol);

                this.socket.SelectedProtocol = protocol;
            }
            else
            {
                throw new OdbException(OdbError.WrongProtocolNumber);
            }
        }
예제 #12
0
        /// <summary>
        /// Register supported pids
        /// </summary>
        /// <param name="ecuIdentifier"></param>
        /// <param name="odbPid"></param>
        /// <param name="pids"></param>
        private void RegisterSupportedPids(int ecuIdentifier, OdbPid odbPid, List <int> pids)
        {
            if (!supportedPids.ContainsKey(ecuIdentifier))
            {
                supportedPids.Add(ecuIdentifier, new Dictionary <OdbPid, List <int> >());
            }

            Dictionary <OdbPid, List <int> > supportedPidsForEcu = supportedPids[ecuIdentifier];

            if (supportedPidsForEcu.ContainsKey(odbPid))
            {
                var pidsSupported = supportedPidsForEcu[odbPid];
                supportedPidsForEcu[odbPid] = pidsSupported.Concat(pids).ToList();
            }
            else
            {
                supportedPidsForEcu.Add(odbPid, pids);
            }
        }
예제 #13
0
        /// <summary>
        /// Resolve incoming data and setup odb data
        /// </summary>
        /// <param name="response"></param>
        /// <param name="what"></param>
        /// <returns></returns>
        public OdbData ResolveData(String response, OdbPid what)
        {
            int counter = 0;

            String[] bytes = response.Split(' ');
            bytes = this.validateReponseBytes(bytes);
            OdbData data = OdbPids.GetResponseFormatForProtocolNumber(bytes.Length, what.ByteCount);

            if (bytes.Length < what.ByteCount)
            {
                return(null);
            }

            try
            {
                data.Protocol = this.SelectedProtocol;
                for (int i = 0; i < data.Header.Length; i++)
                {
                    data.Header[i] = bytes[counter];
                    counter++;
                }
                for (int i = 0; i < data.Info.Length; i++)
                {
                    data.Info[i] = bytes[counter];
                    counter++;
                }
                for (int i = 0; i < data.Data.Length; i++)
                {
                    data.Data[i] = bytes[counter];
                    counter++;
                }
                for (int i = 0; i < data.Ender.Length; i++)
                {
                    data.Ender[i] = bytes[counter];
                    counter++;
                }
            }
            catch
            {
                return(null);
            }
            return(data);
        }
예제 #14
0
        /// <summary>
        /// Send message, return bytes response
        /// </summary>
        /// <param name="what"></param>
        /// <returns></returns>
        public async Task <OdbResponse> Send(OdbPid what)
        {
            if (!this.IsConnected)
            {
                throw new OdbException(OdbError.DeviceIsNotConnected);
            }

            //timer
            DateTime start = DateTime.Now;

            //send
            try
            {
                writer.WriteString(what.Pid + "\r\r");
                await writer.StoreAsync();

                await writer.FlushAsync();
            }
            catch
            {
                this.IsConnected = false;
                throw new OdbException(OdbError.DeviceIsNotConnected);
            }

            //receive data from device
            OdbResponse odbResponse = await receiveDataFromDevice(what, start);

            //try again on error reponse
            while (!odbResponse.IsValid && this.tryCount > 0)
            {
                reporter.ReportInfo("Incorrect response '" + odbResponse.Response + "' from device. Try another request. Current try step is " + this.tryCount + ".");
                odbResponse = await receiveDataFromDevice(what, start);

                this.tryCount--;
            }
            this.tryCount = RESPONSE_TRY_COUNT;

            //report response to console
            reporter.ReportResponse(odbResponse);

            return(odbResponse);
        }
예제 #15
0
        /// <summary>
        /// Decode supported pids and  register it
        /// </summary>
        /// <param name="what"></param>
        /// <param name="data"></param>
        private void decodeSupportedPidsAndRegisterIt(OdbPid what, OdbData data)
        {
            List <int> pids = new List <int>();

            int pid = Convert.ToInt32(what.Pid.Split(' ')[1], 16);

            for (int i = 0; i < data.Data.Length; i++)
            {
                char[] binary = Convert.ToString(Convert.ToInt32(data.Data[i], 16), 2).ToCharArray();
                for (int j = 0; j < binary.Length; j++)
                {
                    pid++;
                    if (binary[j] == '1')
                    {
                        pids.Add(pid);
                    }
                }
            }

            this.RegisterSupportedPids(data.EcuIdentifier(), data.Protocol, pids);
        }
예제 #16
0
        /// <summary>
        /// Is valid response from device
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private bool isValidResponse(String response, OdbPid what)
        {
            var lowerResponse        = response.ToLowerInvariant();
            var rightLength          = lowerResponse.Trim().Length > 0;
            var containsError        = lowerResponse.Contains("error");
            var containsUnknownChars = lowerResponse.Trim() == ">";
            var containsNoData       = lowerResponse.Contains("no data") || lowerResponse.Contains("?");

            //no data is valid response
            if (containsNoData)
            {
                return(true);
            }

            //if is data command then validate data length
            if (what.IsDataCommand && this.ResolveData(response, what) == null)
            {
                return(false);
            }

            //for normal command
            return(rightLength && !containsError && !containsUnknownChars);
        }
예제 #17
0
 /// <summary>
 /// resolve data
 /// </summary>
 /// <param name="response"></param>
 /// <param name="what"></param>
 /// <returns></returns>
 public OdbData ResolveData(OdbResponse response, OdbPid what)
 {
     return(this.ResolveData(response.Response, what));
 }