Пример #1
0
        /// <summary>
        /// Parses a saved configuration file and returns a UscSettings object.
        /// </summary>
        /// <param name="warnings">A list of warnings.  Whenever something goes
        /// wrong with the file loading, a warning will be added to this list.
        /// The warnings are not fatal; if the function returns it will return
        /// a valid UscSettings object.
        /// </param>
        /// <param name="sr">The file to read from.</param>
        /// <remarks>This function is messy.  Maybe I should have tried the XPath
        /// library.</remarks>
        public static UscSettings load(StreamReader sr, List<String> warnings)
        {
            XmlReader reader = XmlReader.Create(sr);

            UscSettings settings = new UscSettings();

            string script = "";

            // The x prefix means "came directly from XML"
            Dictionary<String, String> xParams = new Dictionary<string, string>();

            // Only read the data inside the UscSettings element.
            reader.ReadToFollowing("UscSettings");
            readAttributes(reader, xParams);
            reader = reader.ReadSubtree();

            // Check the version number
            if (!xParams.ContainsKey("version"))
            {
                warnings.Add("This file has no version number, so it might have been read incorrectly.");
            }
            else if (xParams["version"] != "1")
            {
                warnings.Add("Unrecognized settings file version \"" + xParams["version"] + "\".");
            }

            reader.Read(); // this is needed, otherwise the first tag inside uscSettings doesn't work work (not sure why)

            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "Channels")
                {
                    // We found the Channels tag.

                    // Read the ServosAvailable and ServoPeriod attributes from it in to our collection.
                    readAttributes(reader, xParams);

                    // Make a reader that can only read the stuff inside the Channels tag.
                    var channelsReader = reader.ReadSubtree();

                    // For each Channel tag...
                    while(channelsReader.ReadToFollowing("Channel"))
                    {
                        // Read all the attributes.
                        Dictionary<String, String> xChannel = new Dictionary<string, string>();
                        readAttributes(channelsReader, xChannel);

                        // Transform the attributes in to a ChannelSetting object.
                        ChannelSetting cs = new ChannelSetting();
                        if (assertKey("name", xChannel, warnings))
                        {
                            cs.name = xChannel["name"];
                        }

                        if (assertKey("mode", xChannel, warnings))
                        {
                            switch (xChannel["mode"].ToLower())
                            {
                                case "servomultiplied": cs.mode = ChannelMode.ServoMultiplied; break;
                                case "servo": cs.mode = ChannelMode.Servo; break;
                                case "input": cs.mode = ChannelMode.Input; break;
                                case "output": cs.mode = ChannelMode.Output; break;
                                default: warnings.Add("Invalid mode \"" + xChannel["mode"] + "\"."); break;
                            }
                        }

                        if (assertKey("homemode", xChannel, warnings))
                        {
                            switch (xChannel["homemode"].ToLower())
                            {
                                case "goto": cs.homeMode = HomeMode.Goto; break;
                                case "off": cs.homeMode = HomeMode.Off; break;
                                case "ignore": cs.homeMode = HomeMode.Ignore; break;
                                default: warnings.Add("Invalid homemode \"" + xChannel["homemode"] + "\"."); break;
                            }
                        }

                        if (assertKey("min", xChannel, warnings)) { parseU16(xChannel["min"], ref cs.minimum, "min", warnings); }
                        if (assertKey("max", xChannel, warnings)) { parseU16(xChannel["max"], ref cs.maximum, "max", warnings); }
                        if (assertKey("home", xChannel, warnings)) { parseU16(xChannel["home"], ref cs.home, "home", warnings); }
                        if (assertKey("speed", xChannel, warnings)) { parseU16(xChannel["speed"], ref cs.speed, "speed", warnings); }
                        if (assertKey("acceleration", xChannel, warnings)) { parseU8(xChannel["acceleration"], ref cs.acceleration, "acceleration", warnings); }
                        if (assertKey("neutral", xChannel, warnings)) { parseU16(xChannel["neutral"], ref cs.neutral, "neutral", warnings); }
                        if (assertKey("range", xChannel, warnings)) { parseU16(xChannel["range"], ref cs.range, "range", warnings); }

                        settings.channelSettings.Add(cs);
                    }

                    if (channelsReader.ReadToFollowing("Channel"))
                    {
                        warnings.Add("More than " + settings.servoCount + " channel elements were found.  The extra elements have been discarded.");
                    }

                }
                else if (reader.NodeType == XmlNodeType.Element && reader.Name == "Sequences")
                {
                    // We found the Sequences tag.

                    // For each Sequence tag in this sequence...
                    var sequencesReader = reader.ReadSubtree();
                    while (sequencesReader.ReadToFollowing("Sequence"))
                    {
                        // Create a new sequence.
                        Sequence sequence = new Sequence();
                        settings.sequences.Add(sequence);

                        // Read the sequence tag attributes (should just be "name").
                        Dictionary<String, String> sequenceAttributes = new Dictionary<string, string>();
                        readAttributes(sequencesReader, sequenceAttributes);

                        if (sequenceAttributes.ContainsKey("name"))
                        {
                            sequence.name = sequenceAttributes["name"];
                        }
                        else
                        {
                            sequence.name = "Sequence " + settings.sequences.Count;
                            warnings.Add("No name found for sequence " + sequence.name + ".");
                        }

                        // For each frame tag in this sequence...
                        var framesReader = reader.ReadSubtree();
                        while (framesReader.ReadToFollowing("Frame"))
                        {
                            // Create a new frame.
                            Frame frame = new Frame();
                            sequence.frames.Add(frame);

                            // Read the frame attributes from XML (name, duration)
                            Dictionary<String, String> frameAttributes = new Dictionary<string, string>();
                            readAttributes(framesReader, frameAttributes);

                            if (frameAttributes.ContainsKey("name"))
                            {
                                frame.name = frameAttributes["name"];
                            }
                            else
                            {
                                frame.name = "Frame " + sequence.frames.Count;
                                warnings.Add("No name found for " + frame.name + " in sequence \"" + sequence.name + "\".");
                            }

                            if (frameAttributes.ContainsKey("duration"))
                            {
                                parseU16(frameAttributes["duration"], ref frame.length_ms,
                                    "Duration for frame \"" + frame.name + "\" in sequence \"" + sequence.name + "\".", warnings);
                            }
                            else
                            {
                                frame.name = "Frame " + sequence.frames.Count;
                                warnings.Add("No duration found for frame \"" + frame.name + "\" in sequence \"" + sequence.name + "\".");
                            }

                            frame.setTargetsFromString(reader.ReadElementContentAsString(), settings.servoCount);
                        }
                    }
                }
                else if (reader.NodeType == XmlNodeType.Element && reader.Name == "Script")
                {
                    // We found the <Script> tag.

                    // Get the ScriptDone attribute in to our dictionary.
                    readAttributes(reader, xParams);

                    // Read the script.
                    script = reader.ReadElementContentAsString();
                }
                else if (reader.NodeType == XmlNodeType.Element)
                {
                    // Read the miscellaneous parameters that come in element tags, like <NeverSuspend>false</NeverSuspend>.
                    try
                    {
                        xParams[reader.Name] = reader.ReadElementContentAsString();
                    }
                    catch (XmlException e)
                    {
                        warnings.Add("Unable to parse element \"" + reader.Name + "\": " + e.Message);
                    }
                }
            }
            reader.Close();

            //// Step 2: Put the data in to the settings object.

            try
            {
                settings.setAndCompileScript(script);
            }
            catch (Exception e)
            {
                warnings.Add("Error compiling script from XML file: " + e.Message);
                settings.scriptInconsistent = true;
            }

            if (assertKey("NeverSuspend", xParams, warnings))
            {
                parseBool(xParams["NeverSuspend"], ref settings.neverSuspend, "NeverSuspend", warnings);
            }

            if (assertKey("SerialMode", xParams, warnings))
            {
                switch (xParams["SerialMode"])
                {
                    default: settings.serialMode = uscSerialMode.SERIAL_MODE_UART_DETECT_BAUD_RATE; break;
                    case "UART_FIXED_BAUD_RATE": settings.serialMode = uscSerialMode.SERIAL_MODE_UART_FIXED_BAUD_RATE; break;
                    case "USB_DUAL_PORT": settings.serialMode = uscSerialMode.SERIAL_MODE_USB_DUAL_PORT; break;
                    case "USB_CHAINED": settings.serialMode = uscSerialMode.SERIAL_MODE_USB_CHAINED; break;
                }
            }

            if (assertKey("FixedBaudRate", xParams, warnings))
            {
                parseU32(xParams["FixedBaudRate"], ref settings.fixedBaudRate, "FixedBaudRate", warnings);
            }

            if (assertKey("SerialTimeout", xParams, warnings))
            {
                parseU16(xParams["SerialTimeout"], ref settings.serialTimeout, "SerialTimeout", warnings);
            }

            if (assertKey("EnableCrc", xParams, warnings))
            {
                parseBool(xParams["EnableCrc"], ref settings.enableCrc, "EnableCrc", warnings);
            }

            if (assertKey("SerialDeviceNumber", xParams, warnings))
            {
                parseU8(xParams["SerialDeviceNumber"], ref settings.serialDeviceNumber, "SerialDeviceNumber", warnings);
            }

            if (assertKey("SerialMiniSscOffset", xParams, warnings))
            {
                parseU8(xParams["SerialMiniSscOffset"], ref settings.miniSscOffset, "SerialMiniSscOffset", warnings);
            }

            if (assertKey("ScriptDone", xParams, warnings))
            {
                parseBool(xParams["ScriptDone"], ref settings.scriptDone, "ScriptDone", warnings);
            }

            // These parameters are optional because they don't apply to all Maestros.
            if (xParams.ContainsKey("ServosAvailable"))
            {
                parseU8(xParams["ServosAvailable"], ref settings.servosAvailable, "ServosAvailable", warnings);
            }

            if (xParams.ContainsKey("ServoPeriod"))
            {
                parseU8(xParams["ServoPeriod"], ref settings.servoPeriod, "ServoPeriod", warnings);
            }

            if (xParams.ContainsKey("EnablePullups"))
            {
                parseBool(xParams["EnablePullups"], ref settings.enablePullups, "EnablePullups", warnings);
            }

            if (xParams.ContainsKey("MiniMaestroServoPeriod"))
            {
                parseU32(xParams["MiniMaestroServoPeriod"], ref settings.miniMaestroServoPeriod, "MiniMaestroServoPeriod", warnings);
            }

            if (xParams.ContainsKey("ServoMultiplier"))
            {
                parseU16(xParams["ServoMultiplier"], ref settings.servoMultiplier, "ServoMultiplier", warnings);
            }

            return settings;
        }
Пример #2
0
        public static List<Frame> getFromClipboard()
        {
            Frame[] frameArray = Clipboard.GetData("Pololu.Usc.Sequencer.Frame[]") as Frame[];
            if (frameArray != null)
            {
                return new List<Frame>(frameArray);
            }

            Frame frameDirect = Clipboard.GetData("Pololu.Usc.Sequencer.Frame") as Frame;
            if (frameDirect != null)
            {
                return new List<Frame> { frameDirect };
            }

            if (Clipboard.ContainsText())
            {
                // Tab-separated-values for interop with spreadsheet programs.
                List<Frame> frames = new List<Frame>();
                String[] rows = Clipboard.GetText().Split('\n');
                foreach (String row in rows)
                {
                    String[] parts = row.Split('\t');
                    if (parts.Length < 3)
                    {
                        // There are not enough tab-separated parts available
                        // for name, duration, and one target so this line has
                        // no chance of being a frame.  Go to the next line.
                        continue;
                    }

                    Frame frame = new Frame();

                    frame.name = parts[0];

                    // Prevent importing ridiculously long names.
                    if (frame.name.Length > 80)
                    {
                        frame.name = frame.name.Substring(0, 80);
                    }

                    try
                    {
                        frame.length_ms = ushort.Parse(parts[1]);
                    }
                    catch
                    {
                        frame.length_ms = 500;
                    }

                    List<ushort> targets = new List<ushort>();
                    for (int i = 2; i < parts.Length; i++)
                    {
                        try
                        {
                            targets.Add(ushort.Parse(parts[i]));
                        }
                        catch
                        {
                            targets.Add(0);
                        }
                    }

                    frame.targets = targets.ToArray();
                    frames.Add(frame);
                }
                return frames;
            }

            return null;
        }