Saturday, March 22, 2014

RemoteSwitch : send custom commands on bootup and shutdown

Updated to version 1.0.18401.3

RemoteSwitch is a GUI utility that automate the execution of custom command at the startup (OnStart commands) and at closing stage (OnExit commands) of the application.
By adding RemoteSwitch at you workstation startup you can easly configure custom scripts to bootup remote PC, and then shutting it down with your workstation.
RemoteSwitch runs minized to try icon and remote commands can be even executed even by click requests, and eventually disabled.


Custom OnStart and OnExit scripts can be written using external programs, and then added to the RemoteSwitch.xml configuration file.
Change or add a device (es. a remote PC) by editing an XML element to the configuration file:

<Device enabled="1"> <!-- enable or disable the OnStart and OnExit execution of a device -->
<Name>PC1</Name> <!-- device name, must be unique -->
<OnStartEnabled>1</OnStartEnabled> <!-- commands are execute on application startup (OnStart) -->
<OnExitEnabled>1</OnExitEnabled> <!-- commands are execute on application close (OnExit) -->
<OnStartCommand>Commands\bootup_1.bat</OnStartCommand> <!-- OnStart command to be executed -->
<OnExitCommand>Commands\shutdown_1.bat</OnExitCommand> <!-- OnExit command to be executed -->
</Device>

Code

Notes
  • read risk disclaimer
  • excuse my bad english

Monday, March 10, 2014

Electric string winder for guitar, bass and other string instruments



This is an electric string winder for guitar, bass and other string instruments.
This tool is helpful to replace your instruments strings, of course you have to fine tune by hand.


It is almost all built with broken things that laids around in my garage.

The electric screwdriver has non working batteries and no power supply. I replaced the original battery pack with two Ni-MH 1.2V 3800mAh batteries wired in series.


Then i built a NiMH battery charger and embed the battery charger in the screwdriver box. I've found the battery charger design searching for "Low Cost Universal Battery Charger Schematic". The schematics below is just the schematics proposed by the original author, with values i'm using for my power supply / battery pack.


As old mobile phone power supply, 9.2V 440mA.

Then i've built the guitar peg winder, using a plastic guitar peg winder that as the lever broken, and a screwdriver bits worned-out, i cut the broken tip, and then i fixed it to the guitar peg.

Notes
  • read risk disclaimer
  • excuse my bad english

Monday, March 3, 2014

Finding TimeZone by Latitude / Longitude using a TimeZone Shapefile with .NET

Updated to version: 1.0.0.2


A Time Zone is a region that has a uniform standard time for legal, commercial, and social purposes. It is convenient for areas in close commercial or other communication to keep the same time, so time zones tend to follow the boundaries of countries and their subdivisions.

The code snippet proposed here can be used to finding TimeZone by geographical coordinate Latitude / Longitude using a TimeZone Shapefile database on .NET framework

The TimeZone shapefile used for conversion is:
All the library used are open source, also you can find License for those library inside the sample project attached to this post:
At first we need to load all the Geometries contained in the shapefile, and the TimeZone associated, we build a structure used as the container for all data:

private List<GetTimeZones> m_geotimezones = new List<GetTimeZones>();

private class GetTimeZones
{
  public string timezone { get; set; }
  public GeoAPI.Geometries.IGeometry[] geometry { get; set; }
}

Then we load all the data to this container:

public FindTimeZoneByLocation(string shapeFileName)
{
  try
  {
    List<NetTopologySuite.Features.Feature> featureCollection = new List<NetTopologySuite.Features.Feature>();

    //built feature collection from shapefile
    NetTopologySuite.IO.ShapefileDataReader dataReader = new NetTopologySuite.IO.ShapefileDataReader(shapeFileName, new NetTopologySuite.Geometries.GeometryFactory());
    while (dataReader.Read())
    {
      //read current feature
      NetTopologySuite.Features.Feature feature = new NetTopologySuite.Features.Feature();
      feature.Geometry = dataReader.Geometry;
      //get feature keys
      int length = dataReader.DbaseHeader.NumFields;
      string[] keys = new string[length];
      for (int i = 0; i < length; i++)
        keys[i] = dataReader.DbaseHeader.Fields[i].Name;
      //get features attributes
      feature.Attributes = new NetTopologySuite.Features.AttributesTable();
      for (int i = 0; i < length; i++)
      {
        object val = dataReader.GetValue(i);
        feature.Attributes.AddAttribute(keys[i], val);
      }
      //add feature to collection
      featureCollection.Add(feature);
    }
    
    GeoAPI.Geometries.IGeometryFactory gf = GeoAPI.GeometryServiceProvider.Instance.CreateGeometryFactory();
    //built timezones array
    foreach (NetTopologySuite.Features.Feature feature in featureCollection)
    {
      try
      {
        //get timezone
        NetTopologySuite.Features.AttributesTable table = (NetTopologySuite.Features.AttributesTable)feature.Attributes;
        string timezone = table["TZID"].ToString();

        //set getometry
        GeoAPI.Geometries.IGeometry geometry = feature.Geometry;

        bool addnew = true;
        foreach (GetTimeZones geotimezone in m_geotimezones)
        {
          //add geometry to existing timezone
          if (geotimezone.timezone.CompareTo(timezone) == 0)
          {
            addnew = false;
            geotimezone.geometry = geotimezone.geometry.Concat<GeoAPI.Geometries.IGeometry>(new[] { geometry }).ToArray();
          }
        }
        //add a new timezone and his first geometry
        if (addnew)
        {
          GetTimeZones addgeotimezone = new GetTimeZones();
          addgeotimezone.timezone = timezone;
          addgeotimezone.geometry = new[] { geometry };
          m_geotimezones.Add(addgeotimezone);
        }
      }
      catch { }
    }            
  }
  catch { }
}

Then the function that finds if a point, given by latitude / longitude, it also search for the points at a given distance it the exact point is not found, this is usefull for location next to the sea.

public string GetIanaTZName(double latitude, double longitude)
{
  string ret = "";
  
  //make search point
  GeoAPI.Geometries.Coordinate point = new GeoAPI.Geometries.Coordinate(longitude, latitude);

  //loop through zones and search for a point insize the zone
  foreach (GetTimeZones geotimezone in m_geotimezones)
  {
    foreach (GeoAPI.Geometries.IGeometry geometry in geotimezone.geometry)
    {
      try
      {
        if(NetTopologySuite.Algorithm.Locate.SimplePointInAreaLocator.Locate(point, geometry).Equals(GeoAPI.Geometries.Location.Interior))
        {
          ret = geotimezone.timezone;
          return ret;
        }
      }
      catch { }
    }
  }
  
  double distance = 0;
  //set search distance for unfound point
  distance = 0.01;
  if (ret == "")
  {
    foreach (GetTimeZones geotimezone in m_geotimezones)
    {
      foreach (GeoAPI.Geometries.IGeometry geometry in geotimezone.geometry)
      {
        try
        {
          NetTopologySuite.Algorithm.Distance.PointPairDistance ptdist = new NetTopologySuite.Algorithm.Distance.PointPairDistance();
          NetTopologySuite.Algorithm.Distance.DistanceToPoint.ComputeDistance(geometry, point, ptdist);
          if (ptdist.Distance < distance)
          {
            ret = geotimezone.timezone;
            return ret;
          }
        }
        catch { }
      }
    }
  }

  return ret;
}

Attacched a code sample that test the code over more than 5000 points (airports).

Contain also a Iana to Windows TimezoneId conversion based on the http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml conversion file.


Changelog

  • 1.0.0.2: added the IanaToWindows Timezone Id converter
  • 1.0.0.1: first release

Code

Notes
  • read risk disclaimer
  • excuse my bad english