context: /*
      This file is part of HomeGenie Project source code.
  
      HomeGenie is free software: you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation, either version 3 of the License, or
      (at your option) any later version.
  
      HomeGenie is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with HomeGenie.  If not, see <http://www.gnu.org/licenses/>.  
  */
  
  /*
   *     Author: Generoso Martello <gene@homegenie.it>
   *     Project Homepage: http://homegenie.it
   */
  
  /// <summary>
  /// 
  /// Based on code from 
  /// http://www.raspberrypi.org/phpBB3/viewtopic.php?p=88063#p88063
  /// 
  /// </summary>
  
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  
  using MIG.Interfaces.HomeAutomation.Commons;
  
  namespace MIG.Interfaces.EmbeddedSystems
  {
      public class RaspiGPIO : MIGInterface
      {
  
          #region Implemented MIG Commands
  
          // typesafe enum
          public sealed class Command : GatewayCommand
          {
  
              public static Dictionary<int, string> CommandsList = new Dictionary<int, string>()
              {
                  {203, "Parameter.Status"},
                  {701, "Control.On"},
                  {702, "Control.Off"},
                  {731, "Control.Reset"},
              };
  
              // <context>.<command> enum   -   eg. Control.On where <context> :== "Control" and <command> :== "On"
              public static readonly Command PARAMETER_STATUS = new Command(203);
              public static readonly Command CONTROL_ON = new Command(701);
              public static readonly Command CONTROL_OFF = new Command(702);
              public static readonly Command CONTROL_RESET = new Command(731);
  
              private readonly String name;
              private readonly int value;
  
              private Command(int value)
              {
                  this.name = CommandsList[value];
                  this.value = value;
              }
  
              public Dictionary<int, string> ListCommands()
              {
                  return Command.CommandsList;
              }
  
              public int Value
              {
                  get { return this.value; }
              }
  
              public override String ToString()
              {
                  return name;
              }
  
              public static implicit operator String(Command a)
              {
                  return a.ToString();
              }
  
              public static explicit operator Command(int idx)
              {
                  return new Command(idx);
              }
  
              public static explicit operator Command(string str)
              {
                  if (CommandsList.ContainsValue(str))
                  {
                      var cmd = from c in CommandsList where c.Value == str select c.Key;
                      return new Command(cmd.First());
                  }
                  else
                  {
                      throw new InvalidCastException();
                  }
              }
              public static bool operator ==(Command a, Command b)
              {
                  return a.value == b.value;
              }
              public static bool operator !=(Command a, Command b)
              {
                  return a.value != b.value;
              }
          }
  
          #endregion
  
          public Dictionary<string, bool> GpioPins = new Dictionary<string, bool>()
          {
              { "4", false },
              { "17", false },
              { "18", false },
              { "21", false },
              { "22", false },
              { "23", false },
              { "24", false },
              { "25", false }
          };
  
          bool isConnected = false;
  
          public RaspiGPIO()
          {
              isConnected = Directory.Exists(GPIO_PATH);
              CleanUpAllPins();
              //foreach (KeyValuePair<string, bool> kv in GPIOPins)
              //{
              //    GPIOPins[kv.Key] = this.InputPin((enumPIN)int.Parse(kv.Key));
              //}
          }
  
          #region MIG Interface members
  
          public event Action<InterfaceModulesChangedAction> InterfaceModulesChangedAction;
          public event Action<InterfacePropertyChangedAction> InterfacePropertyChangedAction;
  
          public string Domain
          {
              get
              {
                  string domain = this.GetType().Namespace.ToString();
                  domain = domain.Substring(domain.LastIndexOf(".") + 1) + "." + this.GetType().Name.ToString();
                  return domain;
              }
          }
  
          public List<MIGServiceConfiguration.Interface.Option> Options { get; set; }
         
          /// <summary>
          /// get modules and module properties
          /// </summary>
          public List<InterfaceModule> Modules { get; set; }
  
          public List<InterfaceModule> GetModules()
          {
              List<InterfaceModule> modules = new List<InterfaceModule>();
  
              foreach (var rv in GpioPins)
              {
                  InterfaceModule module = new InterfaceModule();
                  module.Domain = this.Domain;
                  module.Address = rv.Key;
                  module.Description = "Raspberry Pi GPIO";
                  module.ModuleType = MIG.ModuleTypes.Switch;
                  modules.Add(module);
              }
  
              return modules;
          }
  
          public bool Connect()
          {
              if (InterfaceModulesChangedAction != null) InterfaceModulesChangedAction(new InterfaceModulesChangedAction(){ Domain = this.Domain });
              return isConnected;
          }
          public void Disconnect()
          {
              CleanUpAllPins();
          }
          public bool IsDevicePresent()
          {
              return isConnected;
          }
          public bool IsConnected
          {
              get { return isConnected; }
          }
  
          public object InterfaceControl(MIGInterfaceCommand request)
          {
              var command = (Command)request.Command;
              string returnvalue = "";
              //
              if (command == Command.CONTROL_ON)
              {
                  this.OutputPin((RaspiGpio)int.Parse(request.NodeId), true);
                  GpioPins[request.NodeId] = true;
                  if (InterfacePropertyChangedAction != null)
                  {
                      try
                      {
                          InterfacePropertyChangedAction(new InterfacePropertyChangedAction() { Domain = this.Domain, SourceId = request.NodeId, SourceType = "Raspberry Pi GPIO", Path = ModuleParameters.MODPAR_STATUS_LEVEL, Value = 1 });
                      }
                      catch { }
                  }
              }
              //
              if (command == Command.CONTROL_OFF)
              {
                  this.OutputPin((RaspiGpio)int.Parse(request.NodeId), false);
                  GpioPins[request.NodeId] = false;
                  if (InterfacePropertyChangedAction != null)
                  {
                      try
                      {
                          InterfacePropertyChangedAction(new InterfacePropertyChangedAction() { Domain = this.Domain, SourceId = request.NodeId, SourceType = "Raspberry Pi GPIO", Path = ModuleParameters.MODPAR_STATUS_LEVEL, Value = 0 });
                      }
                      catch { }
                  }
              }
              //
              if (command == Command.PARAMETER_STATUS)
              {
                  GpioPins[request.NodeId] = this.InputPin((RaspiGpio)int.Parse(request.NodeId));
              }
              //
  
gt:             if (command == Command.CONTROL_RESET)