Beispiel #1
0
        /// <summary>
        /// Called by the constructor to determine whether a VEMCO receiver is attached (vs another kind of 
        /// serial device), what the firmware is and which configuration file should be used.
        /// </summary>
        /// <remarks>
        /// Because one of the goals of this method is to determine the firmware (and corresponding configuration file),
        /// for the most part we must try both "default" commands and all those available in the configuration files.
        /// One assumption here is that future changes to protocol's INFO and discovery methods will not interfere with
        /// the operation of prior receivers.  And although we can take some care to provide as much flexibility for
        /// changes in the protocol, there are clearly some limits.  For example, we cannot anticipate a change to
        /// a binary format.
        /// 
        /// The init() method first attempts to "discover" the connected receiver.  Generally a receiver will not respond
        /// to commands that are not prefaced by the serial number, etc.  Since we do not have the serial number prior to 
        /// running this method, we must use the VEMCO's broadcast and discover commands.
        /// 
        /// Next the method issues INFO commands in order to scrape out the firmware version.  We assume here that the 
        /// manufacturer's protocol will remain stable within a firmware version.  Also note that so long as the protocol
        /// itself does not change, there is no need for additional configuration files.  
        /// 
        /// Assuming that these two tasks are completed without bailing, then init() command completes and returns
        /// control to the constructor.
        /// </remarks>
        /// <exception cref="ReceiverExceptions">Thrown when either the discovery
        /// or info phase is not able to acquire the needed information</exception>
        public void init()
        {
            Dictionary<Double, List<dynamic>> discoveryMethods = new Dictionary<Double, List<dynamic>>();
            Dictionary<Double, String> infoMethods = new Dictionary<Double, String>();
            String discoveryReturns = "";
            
            var jsonParser = new JsonParser() { CamelizeProperties = false };

            foreach (string filename in System.IO.Directory.GetFiles(VR2C_COMMAND_FOLDER))
            {
                dynamic config = jsonParser.Parse(System.IO.File.ReadAllText(filename));
                var dc = config.discovery_commands;
                var fwver = config.firmware_version;
                try
                {
                    infoMethods.Add(fwver, (string)config.encoder["INFO"]);
                }
                catch(Exception e)
                {
                    ReceiverExceptions re = new ReceiverExceptions(this, "INFO command not found in " + 
                        "configuration file: " + filename + ". This is normally not fatal on its own but " +
                        "indicates a serious problem with the format/content of the config file.",
                        false,e);
                    dispatcher.enqueueEvent(new RealTimeEvents.ExcepReceiver(re.fatal, re.ToString(),
                        this, this.portName, null, null, null));
                }

                try
                {
                    discoveryMethods.Add(((int)fwver), dc);
                }
                catch (Exception e)
                {
                    ReceiverExceptions re = new ReceiverExceptions(this, "Discovery commands not found in " +
                        "configuration file: " + filename + ". This is normally not fatal on its own but " +
                        "indicates a serious problem with the format/content of the config file.",
                        false, e);
                    dispatcher.enqueueEvent(new RealTimeEvents.ExcepReceiver(re.fatal, re.text,
                        this, this.portName, null, null, null));
                }
                

            }



            List<dynamic> default_discovery = new List<dynamic>();
            default_discovery.Add("*BROADC.A#ST,QUIT");
            default_discovery.Add("*BROADC.A#ST,DISCOVERY");
            default_discovery.Add("*DISCOV.E#RY,DISCOVERY");
            discoveryMethods.Add(-1, default_discovery);

            int discovery_attempts = 0;
            serialPort.ReadExisting();
            while (serialPort.BytesToRead <= 0 && discovery_attempts < 5)
            {
                write_wait = (discovery_attempts + 1) * 100;
                foreach (List<dynamic> l in discoveryMethods.Values)
                {
                    foreach(var command in l) {
                        _write(command);
                    }
                }
                discovery_attempts++;
            }
            if (discovery_attempts >= 5)
            {
                ReceiverExceptions re = new ReceiverExceptions(this, "Not able to discover VEMCO receiver attached on this port.", true);
                dispatcher.enqueueEvent(new RealTimeEvents.ExcepReceiver(re,re.fatal, 
                    this, this.portName, null,null, null));
                serialPort.Close();
                throw re;
            }

            while (serialPort.BytesToRead > 0)
            {
                discoveryReturns = serialPort.ReadExisting();
            }
            

            string commandPreamble = discoveryReturns.Substring(0, 12) + ",";
            this.VEMCO_SerialNumber = discoveryReturns.Substring(1,6);
            dispatcher.enqueueEvent(new RealTimeEvents.NoteReceiver("command preamble: " + discoveryReturns.Substring(0,12) + ",",
                this, this.portName, this.VEMCO_SerialNumber, null, null));
            dispatcher.enqueueEvent(new RealTimeEvents.NoteReceiver("read: " + discoveryReturns,
                this, this.portName, this.VEMCO_SerialNumber, null, null));

            infoMethods.Add(-1, commandPreamble + "INFO");
            int info_attempts = 0;
            serialPort.ReadExisting();
            Boolean gotINFO = false;
            String infoReturns = "";
            int read_attempts = 0;

            while (!gotINFO && read_attempts < 5)
            {
                info_attempts = 0;
                serialPort.ReadExisting();
                while (serialPort.BytesToRead <= 0 && info_attempts < 5)
                {
                    foreach (String infoc in infoMethods.Values)
                    {
                        dispatcher.enqueueEvent(new RealTimeEvents.NoteReceiver("(receiver note) attempting INFO command with " + infoc,
                            this, this.portName, this.VEMCO_SerialNumber, null, null));
                        _write(infoc);
                        Thread.Sleep(500);
                    }
                    info_attempts++;
                }

                while (serialPort.BytesToRead > 0 && !(infoReturns.Contains(crlf[0]) || infoReturns.Contains(crlf[1])))
                {
                    infoReturns = serialPort.ReadExisting();

                    foreach (string filename in System.IO.Directory.GetFiles(VR2C_COMMAND_FOLDER))
                    {
                        dynamic config = jsonParser.Parse(System.IO.File.ReadAllText(filename));
                        if (Regex.IsMatch(infoReturns, config.decoder.sentences["info_response"].format))
                        {
                            gotINFO = true;
                        }

                    }
                }
                read_attempts++;
            }
            if (read_attempts >= 5)
            {
                ReceiverExceptions re = new ReceiverExceptions(this, "(FATAL) Not able to get INFO from the VEMCO receiver attached on this port.", true);
                dispatcher.enqueueEvent(new RealTimeEvents.ExcepReceiver(re, re.fatal,
                    this, this.portName, this.VEMCO_SerialNumber, null, null));
                serialPort.Close();
                throw re;
            }

            int RECEIVER_FW_VERSION = -1;
            if (infoReturns != "")
            {
                
                int fw_start = infoReturns.IndexOf("FW=");
                int fw_end = infoReturns.IndexOf(",", fw_start);
                string fw_ver = infoReturns.Substring((fw_start + 3), (fw_end - fw_start - 3));
                int fw_ver_firstperiod = fw_ver.IndexOf(".");
                int fw_ver_secondperiod = fw_ver.IndexOf(".", fw_ver_firstperiod + 1);
                string major = fw_ver.Substring(0, fw_ver_firstperiod);
                string minor = fw_ver.Substring(fw_ver_firstperiod + 1, (fw_ver_secondperiod - fw_ver_firstperiod - 1));
                string release = fw_ver.Substring(fw_ver_secondperiod + 1, (fw_ver.Length - fw_ver_secondperiod - 1));
                RECEIVER_FW_VERSION = (Int32.Parse(major) * 10000) + (Int32.Parse(minor) * 100) + (Int32.Parse(release));
            }
            dispatcher.enqueueEvent(new RealTimeEvents.NoteReceiver("Detected firmware version: " + RECEIVER_FW_VERSION,
                this, this.portName, this.VEMCO_SerialNumber, this.VEMCO_Model, null));
            if (RECEIVER_FW_VERSION >= 0)
            {
                int fw_use = -1;

                foreach (string filename in System.IO.Directory.GetFiles(VR2C_COMMAND_FOLDER))
                {

                    string text = System.IO.File.ReadAllText(filename);
                    dynamic config = jsonParser.Parse(System.IO.File.ReadAllText(filename));

                    if (config.firmware_version >= fw_use && config.firmware_version <= RECEIVER_FW_VERSION)
                    {
                        fw_use = (Int32)config.firmware_version;
                        
                        encoder = new Encoder(commandPreamble, config);
                    }
                }
                if (fw_use < 0 || encoder == null)
                {
                    ReceiverExceptions re = new ReceiverExceptions(this, "(FATAL) Unable to parse out FW version from return from INFO command.", true);
                    dispatcher.enqueueEvent(new RealTimeEvents.ExcepReceiver(re, re.fatal,
                        this, this.portName, this.VEMCO_SerialNumber, null, null));
                    serialPort.Close();
                    throw re;
                }
            }
            else
            {
                ReceiverExceptions re = new ReceiverExceptions(this, "(FATAL) Unable to parse out FW version from return from INFO command.", true);
                dispatcher.enqueueEvent(new RealTimeEvents.ExcepReceiver(re,re.fatal,
                    this, this.portName, this.VEMCO_SerialNumber, null, null));
                serialPort.Close();
                throw re;
            }
            Match matches = Regex.Match(infoReturns, encoder.encoderConfig.decoder.words["receiver_model"]);
            VEMCO_Model = matches.Groups[1].ToString();
            dispatcher.enqueueEvent(new RealTimeEvents.NoteReceiver("(receiver note) Successfully configured encoder with fw version = " + encoder.encoderConfig.firmware_version,
                this, this.portName, this.VEMCO_SerialNumber, this.VEMCO_Model, this.encoder.encoderConfig));
        }