Beispiel #1
0
        /// <summary>
        /// This is a console example of importing Zones from a .csv file.
        ///
        /// 1) Process command line arguments: Server, Database, Username, Password, Options and Load .csv file.
        ///    Note: the .csv file in this project is a sample, you may need to change entries (such as group names) for the example to work.
        /// 2) Create Geotab API object and Authenticate.
        /// 3) Import zones into database.
        ///
        /// A complete Geotab API object and method reference is available at the Geotab Developer page.
        /// </summary>
        /// <param name="args">The command line arguments for the application. Note: When debugging these can be added by: Right click the project > Properties > Debug Tab > Start Options: Command line arguments.</param>
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 5)
                {
                    Console.WriteLine();
                    Console.WriteLine("Command line parameters:");
                    Console.WriteLine("dotnet run <server> <database> <username> <password> [-poly=<##>] [-type=<name>] <inputfile>");
                    Console.WriteLine();
                    Console.WriteLine("Command line:      dotnet run server database username password -poly=6 -type=home inputfile");
                    Console.WriteLine("server             - The server name (Example: my.geotab.com)");
                    Console.WriteLine("database           - The database name (Example: G560)");
                    Console.WriteLine("username           - The Geotab user name");
                    Console.WriteLine("password           - The Geotab password");
                    Console.WriteLine("--poly=##           - Optional - Draw the zone as an N-sided polygon. (Default: 4)");
                    Console.WriteLine("--type=<name>       - Optional - Specify zone type as customer, home, or office. (Default: customer)");
                    Console.WriteLine("inputfile          - File name of the CSV file to import.");
                    Console.WriteLine();
                    return;
                }

                // Variables from command line
                int    last         = args.Length - 1;
                string server       = args[0];
                string database     = args[1];
                string username     = args[2];
                string password     = args[3];
                string filename     = args[last];
                int    polygonSides = 4;

                IList <ZoneType> zoneTypes = new List <ZoneType>();

                // Options from args
                for (int i = 4; i < last; i++)
                {
                    string option = args[i].ToLowerInvariant();

                    // Poly sides option
                    if (option.Contains("poly"))
                    {
                        int index = option.IndexOf('=');
                        if (index >= 0 && option.Length > index + 1)
                        {
                            if (int.TryParse(option.Substring(index + 1), out int value) && value > 2)
                            {
                                polygonSides = value;
                            }
                        }
                    }

                    // Zone type option
                    else if (option.Contains("type"))
                    {
                        int index = option.IndexOf('=');
                        if (index >= 0 && option.Length > index + 1)
                        {
                            string   value    = option.Substring(index + 1).ToLowerInvariant();
                            ZoneType zoneType = null;
                            if (value.Contains("customer"))
                            {
                                zoneType = ZoneTypeCustomer.Value;
                            }
                            else if (value.Contains("home"))
                            {
                                zoneType = ZoneTypeHome.Value;
                            }
                            else if (value.Contains("office"))
                            {
                                zoneType = ZoneTypeOffice.Value;
                            }
                            if (zoneType != null && !zoneTypes.Contains(zoneType))
                            {
                                zoneTypes.Add(zoneType);
                            }
                        }
                    }
                }

                // Use Customer Zone Type for default.
                if (zoneTypes.Count == 0)
                {
                    zoneTypes.Add(ZoneTypeCustomer.Value);
                }

                // Load .csv file entries into a collection of customers
                Console.WriteLine("Loading CSV file...");
                List <ZoneRow> zoneRows;
                try
                {
                    zoneRows = LoadZonesFromCSV(filename);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"Could not load CSV file: {exception.Message}");
                    return;
                }

                // Create Geotab API object
                API api = new API(username, password, null, database, server);

                // Authenticate
                Console.WriteLine("Authenticating...");
                api.Authenticate();

                // Get user
                User user = api.Call <User>("RefreshUser");

                // Start import
                Console.WriteLine("Importing...");

                IList <Zone>  zones     = api.Call <IList <Zone> >("Get", typeof(Zone));
                IList <Group> allGroups = api.Call <IList <Group> >("Get", typeof(Group));

                // We only want to be able to assign Organization Group if the API user has this in their scope.
                bool hasOrgGroupScope = false;

                // See if the API user has Organization Group in their Groups
                foreach (Group group in user.CompanyGroups)
                {
                    if (group is CompanyGroup || group is RootGroup)
                    {
                        hasOrgGroupScope = true;
                        break;
                    }
                }

                // Set the zone color based on type.
                // Geotab uses standard colors for the stock zone types. Colors are noted at the top of this class.
                Color zoneColor = customerZoneColor;
                if (zoneTypes.Count > 0)
                {
                    ZoneType type = zoneTypes[0];
                    if (type is ZoneTypeHome)
                    {
                        zoneColor = homeZoneColor;
                    }
                    else if (type is ZoneTypeOffice)
                    {
                        zoneColor = officeZoneColor;
                    }
                }

                // Add zones
                foreach (ZoneRow zoneRow in zoneRows)
                {
                    Group group;

                    // If there are no nodes for the zone specified in the .csv we will try to assign to Organization
                    if (hasOrgGroupScope && string.IsNullOrEmpty(zoneRow.NodeName))
                    {
                        group = new CompanyGroup();
                    }

                    // Organization group
                    else if (hasOrgGroupScope && zoneRow.NodeName.Trim().ToLowerInvariant() == "organization" || zoneRow.NodeName.Trim().ToLowerInvariant() == "entire organization")
                    {
                        group = new CompanyGroup();
                    }
                    else
                    {
                        // Get the group from allGroups
                        group = GetGroup(zoneRow.NodeName.Trim(), allGroups);
                        if (group == null)
                        {
                            Console.WriteLine($"Zone Rejected: '{zoneRow.Name}'. Group: '{zoneRow.NodeName}' does not exist.");
                            continue;
                        }
                    }

                    // Check for an existing zone
                    if (ZoneExists(zoneRow.Name, zoneRow.NodeName, zones))
                    {
                        Console.WriteLine($"Zone exists: '{zoneRow.Name}'.");
                        continue;
                    }

                    // Check for an existing zone
                    try
                    {
                        // Create a new zone object
                        Zone zone = CreateCircleZone(zoneRow.Name, "", zoneRow.Latitude, zoneRow.Longitude, zoneRow.Size, polygonSides, zoneTypes, zoneColor, new List <Group> {
                            group
                        });
                        api.Call <Id>("Add", typeof(Zone), new { entity = zone });
                        Console.WriteLine($"Zone: '{zoneRow.Name}' added");
                    }
                    catch (Exception ex)
                    {
                        // Catch and display any error that occur when adding the zone
                        Console.WriteLine($"Error adding zone: '{zoneRow.Name}'\n{ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                // Show miscellaneous exceptions
                Console.WriteLine($"Error: {ex.Message}\n{ex.StackTrace}");
            }
            finally
            {
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey(true);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Create a new circle zone.
        /// </summary>
        /// <param name="name">The zone name.</param>
        /// <param name="comment">The zone comment.</param>
        /// <param name="longitude">The longitude of the center point of the zone.</param>
        /// <param name="latitude">The latitude of the center point of the zone.</param>
        /// <param name="size">The size.</param>
        /// <param name="polygonSides">The number of polygon sides.</param>
        /// <param name="zoneTypes">The zone types.</param>
        /// <param name="color">The color.</param>
        /// <param name="groups">The nodes.</param>
        /// <returns>
        /// A new zone.
        /// </returns>
        static Zone CreateCircleZone(string name, string comment, double longitude, double latitude, double size, int polygonSides, IList <ZoneType> zoneTypes, Color color, IList <Group> groups)
        {
            double diagonal = 0.001F * size;
            IList <ISimpleCoordinate> circleCoordinates = GetCircleCoordinates(new Coordinate(longitude, latitude), diagonal / 2, polygonSides);

            return(new Zone(null, name, comment, true, zoneTypes, circleCoordinates, DateTime.MinValue, System.TimeZoneInfo.ConvertTimeToUtc(DateTime.MaxValue), color, true, groups));
        }
Beispiel #3
0
        /// <summary>
        /// This is a console example of importing zones of a specified type from a shape file set (.shp, .shx, .dbf) or csv file into a specified database.
        /// Included in this project is are sample shape files: owensboro
        ///
        /// 1) Process command line arguments: Server, Database, User name, Password, Options and load the specified shape/csv file set.
        /// 2) Process the shapes present in the shape file, using the Geotab.Geographical components to create zones from the shape points and names.
        /// 3) Create Geotab API object and Authenticate.
        /// 4) Import created zones into the database.
        /// The format of csv file is next:
        /// [Zone_name]
        /// [polygon_point_x], [polygon_point_y]
        /// [polygon_point_x], [polygon_point_y]
        /// .
        /// .
        /// [polygon_point_x], [polygon_point_y]
        /// [Zone_name]
        /// [polygon_point_x], [polygon_point_y]
        /// .
        /// .
        /// A complete Geotab API object and method reference is available at the Geotab Developer page.
        /// </summary>
        /// <param name="args">The command line arguments for the application. Note: When debugging these can be added by: Right click the project > Properties > Debug Tab > Start Options: Command line arguments.</param>
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 5)
                {
                    Console.WriteLine();
                    Console.WriteLine("Command line parameters:");
                    Console.WriteLine("dotnet run <server> <database> <login> <password> [--nameAttr=<attr>] [--namePrefix=<prefix>] [--type=<name>] <inputfile>");
                    Console.WriteLine();
                    Console.WriteLine("Command line:             dotnet run server database username password --nameAttr=name --namePrefix=CA --type=home inputfile.shp");
                    Console.WriteLine("server                   - The server name (Example: my.geotab.com)");
                    Console.WriteLine("database                 - The database name (Example: G560)");
                    Console.WriteLine("username                 - The Geotab user name");
                    Console.WriteLine("password                 - The Geotab password");
                    Console.WriteLine("[--nameAttr=<attr>]      - Optional - Name of the shape's attribute to use as");
                    Console.WriteLine("                           the zone name. (Default: first attribute containing");
                    Console.WriteLine("                           the word 'name')");
                    Console.WriteLine("[--namePrefix=<prefix>]  - Optional - The name prefix. (Example: prefix + Name)");
                    Console.WriteLine("[--type=<name>]          - Optional - Specify zone type (Default: customer)");
                    Console.WriteLine("[--threshold=<number>]   - Optional - Simplify zones by removing redundant");
                    Console.WriteLine("                           points. Any point within approximately <threshold>");
                    Console.WriteLine("                           meters of a line connecting its neighbors will be");
                    Console.WriteLine("                           removed.");
                    Console.WriteLine("inputfile                - File name of the Shape file containing the shapes to");
                    Console.WriteLine("                           import with extension. (.shp, .shx, .dbf)");
                    Console.WriteLine();
                    return;
                }

                // Variables from command line
                int             last                 = args.Length - 1;
                string          server               = args[0];
                string          database             = args[1];
                string          username             = args[2];
                string          password             = args[3];
                List <ZoneType> zoneTypes            = new List <ZoneType>();
                string          fileName             = args[last];
                string          nameAttribute        = null;
                string          prefix               = "";
                double          distanceSquaredError = -1;
                Color           zonesColour          = customerZoneColor;

                // Create Geotab API object
                API api = new API(username, password, null, database, server);

                // Authenticate
                Console.WriteLine("Authenticating...");
                api.Authenticate();

                Console.WriteLine("Getting current user...");
                List <User> users = api.Call <List <User> >("Get", typeof(User), new { search = new UserSearch {
                                                                                           Name = api.UserName
                                                                                       } });
                if (users.Count != 1)
                {
                    Console.WriteLine($"Found {users.Count} users with name {api.UserName}.");
                    return;
                }

                // the user's groups will be used when creating the zones
                var groups = users[0].CompanyGroups;

                Console.WriteLine("Getting available zone types...");
                List <ZoneType> availableZoneTypes = api.Call <List <ZoneType> >("Get", typeof(ZoneType));

                // Options from args
                for (int i = 4; i < last; i++)
                {
                    string option = args[i].ToLowerInvariant();
                    int    index  = option.IndexOf('=');

                    // Check the option is in the established format
                    if (index >= 0 && option.Length > index + 1)
                    {
                        // Grab the value of the optional argument
                        string value = option.Substring(index + 1).ToLowerInvariant();

                        // Zone type option
                        if (option.Contains("type"))
                        {
                            ZoneType zoneType = GetZoneType(value, availableZoneTypes);

                            if (zoneType != null && !zoneTypes.Contains(zoneType))
                            {
                                // Setting a default colour
                                switch (zoneType.Name)
                                {
                                case "**Customer Zone":
                                    zonesColour = customerZoneColor;
                                    break;

                                case "**Home Zone":
                                    zonesColour = homeZoneColor;
                                    break;

                                case "**Office Zone":
                                    zonesColour = officeZoneColor;
                                    break;
                                }

                                zoneTypes.Add(zoneType);
                            }
                        }

                        // Name attribute option
                        else if (option.Contains("nameattr"))
                        {
                            nameAttribute = value;
                        }

                        // Name prefix option
                        else if (option.Contains("prefix"))
                        {
                            prefix = value.ToUpperInvariant();
                        }

                        // Zone shape simplification threshold option
                        else if (option.Contains("threshold"))
                        {
                            if (!double.TryParse(value, out double threshold))
                            {
                                Console.WriteLine("Threshold must be a number. Example: 2.5");
                            }
                            else
                            {
                                distanceSquaredError = Math.Pow(1e-5 * threshold, 2);
                            }
                        }

                        else
                        {
                            Console.WriteLine($"Unknown optional argument: {option}");
                        }
                    }
                    else
                    {
                        Console.WriteLine($"Unknown format for optional argument: {option}");
                    }
                }

                // Use Customer Zone Type for default.
                if (zoneTypes.Count < 1)
                {
                    zoneTypes.Add(ZoneTypeCustomer.Value);
                }

                IList <ISimpleCoordinate> coordinates = new List <ISimpleCoordinate>();
                IList <Zone> zones = new List <Zone>();

                // Initialize variables to hold the shape file
                DateTime maxValue = System.TimeZoneInfo.ConvertTimeToUtc(DateTime.MaxValue);
                DateTime minValue = DateTime.MinValue;
                if (!string.IsNullOrEmpty(fileName) && Path.GetExtension(fileName).ToLower().Contains("csv"))
                {
                    if (!File.Exists(fileName))
                    {
                        Console.WriteLine($"The file {fileName} does not exist.");
                        return;
                    }
                    Console.WriteLine("Loading csv file...");
                    using (StreamReader reader = File.OpenText(fileName))
                    {
                        string line;
                        string zoneName = string.Empty;
                        while (!string.IsNullOrEmpty(line = reader.ReadLine()))
                        {
                            string[] values = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                            if (values.Length == 0 || values.Length == 1 && string.IsNullOrWhiteSpace(values[0]))
                            {
                                continue;
                            }
                            switch (values.Length)
                            {
                            case 1:
                                if (!string.IsNullOrEmpty(values[0]))
                                {
                                    if (!string.IsNullOrEmpty(zoneName))
                                    {
                                        // Simplify the zone shape. This is an important step. Polygon complexity can drastically impact performance when loading/rendering zones.
                                        coordinates = SimplifyPolygon(coordinates, distanceSquaredError);

                                        // Create the zone object to be inserted later on
                                        zones.Add(new Zone(null, (string.IsNullOrEmpty(prefix) ? "" : prefix + " ") + zoneName, "", true, zoneTypes, coordinates, minValue, maxValue, zonesColour, true, groups));
                                    }
                                    coordinates = new List <ISimpleCoordinate>();
                                    zoneName    = values[0];
                                }
                                break;

                            case 2:

                                // read coordinates line by line
                                if (double.TryParse(values[0], out var xCoord) && double.TryParse(values[1], out var yCoord))
                                {
                                    coordinates.Add(new Coordinate(xCoord, yCoord));
                                }
                                break;

                            default:
                                Console.WriteLine($"Skipping a line with text '{line}'");
                                break;
                            }
                        }
                        if (!string.IsNullOrEmpty(zoneName))
                        {
                            coordinates = SimplifyPolygon(coordinates, distanceSquaredError);
                            zones.Add(new Zone(null, (string.IsNullOrEmpty(prefix) ? "" : prefix + " ") + zoneName, "", true, zoneTypes, coordinates, minValue, maxValue, zonesColour, true, groups));
                        }
                    }
                }
                else
                {
                    FileInfo            shapeFile = new FileInfo(fileName);
                    FileMapLayerFactory factory   = new FileMapLayerFactory(shapeFile);
                    ShapeFileLayer      layer;

                    // Try to load the shape file
                    Console.WriteLine("Loading shape file...");
                    try
                    {
                        layer = (ShapeFileLayer)factory.GetMapLayer();
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine($"Could not load shape file: {exception.Message}");
                        return;
                    }

                    // Get the index of the feature attribute that holds the zone name
                    Console.WriteLine("__ " + nameAttribute);
                    int nameAttributeIndex = GetNameAttributeIndex(layer, ref nameAttribute);
                    if (nameAttributeIndex == -1)
                    {
                        Console.WriteLine("Could not find a valid attribute to use for naming the zones.");
                        return;
                    }

                    // Process shapes into zones
                    int featureIndex = 0;
                    for (int k = 0; k < layer.Features.Count; k++)
                    {
                        IEarthFeature earthFeature = layer.Features[k];

                        // Get the data we are interested in for the zone
                        IEarthPolygon polygon  = earthFeature as IEarthPolygon;
                        string        zoneName = layer.GetFeatureField(featureIndex, nameAttributeIndex).ToString();

                        // Filter out non-polygons and unnamed shapes
                        if (polygon == null || string.IsNullOrEmpty(zoneName))
                        {
                            featureIndex++;
                            continue;
                        }

                        // Get the points that define the polygon
                        coordinates = new List <ISimpleCoordinate>();
                        for (int i = 0; i < polygon.Count; i++)
                        {
                            EarthPoint        earthPoint = (EarthPoint)polygon[i];
                            ISimpleCoordinate coordinate = new Coordinate(earthPoint.X, earthPoint.Y);
                            coordinates.Add(coordinate);
                        }

                        // Simplify the polygon. This is an important step. Polygon complexity can drastically impact performance when loading/rendering zones.
                        coordinates = SimplifyPolygon(coordinates, distanceSquaredError);

                        zones.Add(new Zone(null, (string.IsNullOrEmpty(prefix) ? "" : prefix + " ") + zoneName, "", true, zoneTypes, coordinates, minValue, maxValue, zonesColour, true, groups));
                        featureIndex++;
                    }
                }

                Console.WriteLine($"Found {zones.Count} zones to import");

                if (zones.Count < 1)
                {
                    return;
                }

                // Start import
                Console.WriteLine("Importing zones...");

                foreach (Zone zone in zones)
                {
                    try
                    {
                        // Add the zone
                        api.Call <Id>("Add", typeof(Zone), new { entity = zone });
                        Console.WriteLine($"Zone: '{zone.Name}' added");
                    }
                    catch (Exception exception)
                    {
                        // Catch and display any error that occur when adding the zone
                        Console.WriteLine($"Error adding zone: '{zone.Name}'\n{exception.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                // Show miscellaneous exceptions
                Console.WriteLine($"Error: {ex.Message}\n{ex.StackTrace}");
            }
            finally
            {
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey(true);
            }
        }