public JsonObject GetDiskInfo()
 {
   try
   {
     var diskinfo = new JsonObject();
     var volumes = new ArrayList();
     foreach (var vi in VolumeInfo.GetVolumes())
     {
       var v = new Hashtable();
       v.Add("root", vi.RootDirectory);
       v.Add("size", vi.TotalSize);
       v.Add("free", vi.TotalFreeSpace);
       v.Add("formatted", vi.IsFormatted);
       v.Add("volumeid", vi.VolumeID);
       v.Add("content", GetRootFolderInfo(vi.RootDirectory));
       volumes.Add(v);
     }
     diskinfo.Add("volumes", volumes);
     return diskinfo;
   }
   catch (Exception ex)
   {
     var error = new JsonObject();
     error.Add("error", ex.ToString());
     error.Add("stacktrace", ex.StackTrace);
     return error;
   }
 }
    public void Start(Power firmware)
    {
      var config = new RestApiConfiguration();

      config.AddHandler("GET", "/boot/ping", "is server alive")
        .ReturnNothing()
        .HandledBy(() => {});

      config.AddHandler("GET", "/boot/firmware", "get firmware info")
        .ReturnJson()
        .HandledBy(() => firmware.GetFirmwareInfoAsJson());

      config.AddHandler("PUT", "/boot/firmware", "update firmware")
        .ReturnJson()
        .HandledWithStreamBy((s) => firmware.UpdateFirmware(s));

      config.AddHandler("POST", "/boot/sysinfo", "get system state")
        .ReturnJson()
        .HandledBy(() => HardwareInfo.Instance.GetSystemInfo());

      config.AddHandler("POST", "/boot/diskinfo", "list content of filesystem")
        .ReturnJson()
        .HandledBy(() => HardwareInfo.Instance.GetDiskInfo());

      config.AddHandler("GET", "/boot/networks", "list network information")
        .ReturnJson()
        .HandledBy(() => HardwareInfo.Instance.GetNetworkInterfaceInfo());

      config.AddHandler("GET", "/boot/log/full", "get full log")
        .ReturnJson()
        .HandledBy(() => Logger.Instance.Full.GetLinesAsJson());

      config.AddHandler("GET", "/boot/log/errors", "get error log")
        .ReturnJson()
        .HandledBy(() => Logger.Instance.Errors.GetLinesAsJson());

      config.AddHandler("POST", "/boot/ntp/sync", "sync time with NTP")
        .ReturnJson()
        .HandledBy(() =>
        {
          RealTimeClock.Instance.UpdateFromNTP();
          var status = new JsonObject();
          status.Add("time", DateTime.Now);
          return status;
        });

      config.AddHandler("POST", "/boot/reboot", "reboot the device")
        .SetNotes("This will reboot the device and not return")
        .ReturnNothing()
        .HandledBy(() => firmware.Reboot());

      var credentials = CredentialValidatorFactory.CreateSimpleValidator("ChickenHouse", "admin", "hnsefyk");
      var webService = new WebService(c_servicePort, credentials, config);

      string prefix = Name + ": ";
      webService.Logging.OnLogInfo += message => Logger.Instance.LogInfo(prefix + message);
      webService.Logging.OnLogError += message => Logger.Instance.LogError(prefix + message);
      webService.Logging.OnLogException += (message, ex) => Logger.Instance.LogException(prefix + message, ex);
      webService.Start();
    }
 public JsonObject GetSystemInfo()
 {
   var freeMem = Debug.GC(true);
   var sysinfo = new JsonObject();
   sysinfo.Add("uptimeInSec", PowerState.Uptime.Ticks / TimeSpan.TicksPerSecond);
   sysinfo.Add("sysVersion", SystemInfo.Version.ToString());
   sysinfo.Add("timeNow", DateTime.Now);
   sysinfo.Add("utcNow", DateTime.UtcNow);
   sysinfo.Add("freeMemoryInBytes", freeMem);
   return sysinfo;
 }
 public JsonObject GetNetworkInterfaceInfo()
 {
   var networkinfo = new JsonObject();
   var networks = new ArrayList();
   foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces())
   {
     var network = new Hashtable();
     network.Add("ipAddress", networkInterface.IPAddress);
     network.Add("gateway", networkInterface.GatewayAddress);
     byte[] pa = networkInterface.PhysicalAddress;
     var physicalAddress = pa.Length == 6 ? pa[0] + "-" + pa[1] + "-" + pa[2] + "-" + pa[3] + "-" + pa[4] + "-" + pa[5] : "(none)";
     network.Add("mac", physicalAddress);
     network.Add("subnetMask", networkInterface.SubnetMask);
     var dnsAddresses = new ArrayList();
     foreach (var dns in networkInterface.DnsAddresses)
     {
       dnsAddresses.Add(dns);
     }
     network.Add("dns", dnsAddresses);
     network.Add("dhcp", networkInterface.IsDhcpEnabled);
     network.Add("dynamicDns", networkInterface.IsDynamicDnsEnabled);
     network.Add("nicType", (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet ? "ethernet" :
                             networkInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ? "wireless"  :
                             "unknown"));
     networks.Add(network);
   }
   networkinfo.Add("networks", networks);
   return networkinfo;
 }
    public void Start(Machinery machinery, DoorScheduler doorScheduler)
    {
      var config = new RestApiConfiguration();

      config.AddHandler("GET", "/sys/ping", "is server alive")
        .ReturnsNothing()
        .HandledBy(() => { });

      config.AddHandler("POST", "/sys/info", "get system state")
        .ReturnsJson()
        .HandledBy(() => HardwareInfo.Instance.GetSystemInfo());

      config.AddHandler("POST", "/sys/disk", "list content of filesystem")
        .ReturnsJson()
        .HandledBy(() => HardwareInfo.Instance.GetDiskInfo());

      config.AddHandler("GET", "/sys/network", "list network information")
        .ReturnsJson()
        .HandledBy(() => HardwareInfo.Instance.GetNetworkInterfaceInfo());

      config.AddHandler("GET", "/sys/time", "get current local time")
        .ReturnsJson()
        .HandledBy(() =>
        {
          var status = new JsonObject();
          status.Add("time", DateTime.Now);
          return status;
        });

      config.AddHandler("PUT", "/sys/time/{time}", "set current local time")
        .ReturnsNothing()
        .HandledBy((time) =>
        {
          // todo
          //Goke.ChickenHouse.HAL.Hardware.Instance.Clock.SetTime(
          var x = time.Length;
          throw new NotImplementedException("set time is not implemented yet");
        });

      config.AddHandler("POST", "/sys/time/sync", "sync time with NTP")
        .ReturnsJson()
        .HandledBy(() =>
        {
          RealTimeClock.Instance.UpdateFromNTP();
          var status = new JsonObject();
          status.Add("time", DateTime.Now);
          return status;
        });

      config.AddHandler("POST", "/sys/reboot", "reboot the device")
        .SetNotes("This will reboot the device and not return")
        .ReturnsNothing()
        .HandledBy(() => MainBoard.Reboot());


      config.AddHandler("GET", "/hw/doors/{doorname}", "get status for the door")
        .ReturnsJson()
        .HandledBy((doorname) =>
          {
            var door = machinery.LookupDoorByName(doorname);
            var status = new JsonObject();
            status.Add("name", door.Name);
            status.Add("status", EnumUtil.DoorStatusTostring(door.Status));
            return status;
          });

      config.AddHandler("POST", "/hw/doors/{doorname}/open", "open the door completely")
        .ReturnsNothing()
        .HandledBy((doorname) =>
          {
            var door = machinery.LookupDoorByName(doorname);
            machinery.Sequencer.Enqueue(() => door.OpenCompletely());
          });

      config.AddHandler("POST", "/hw/doors/{doorname}/close", "close the door completely")
        .ReturnsNothing()
        .HandledBy((doorname) =>
          {
            var door = machinery.LookupDoorByName(doorname);
            machinery.Sequencer.Enqueue(() => door.CloseCompletely());
          });

      config.AddHandler("POST", "/hw/doors/{doorname}/moveup/{millisec}", "move the door up")
        .ReturnsNothing()
        .HandledBy((doorname, millisec) =>
          {
            var door = machinery.LookupDoorByName(doorname);
            var msec = int.Parse(millisec);
            machinery.Sequencer.Enqueue(() => door.MoveUp(msec));
          });

      config.AddHandler("POST", "/hw/doors/{doorname}/movedown/{millisec}", "move the door down")
        .ReturnsNothing()
        .HandledBy((doorname, millisec) =>
          {
            var door = machinery.LookupDoorByName(doorname);
            var msec = int.Parse(millisec);
            machinery.Sequencer.Enqueue(() => door.MoveDown(msec));
          });

      config.AddHandler("POST", "/hw/doors/{doorname}/stop", "stop moving the door")
        .ReturnsNothing()
        .HandledBy((doorname) =>
          {
            var door = machinery.LookupDoorByName(doorname);
            door.StopMoving(); // Stop immediately - don't go through sequencer!
          });

      config.AddHandler("GET", "/hw/relays/{relayname}", "get state of relay")
        .ReturnsJson()
        .HandledBy((relayname) =>
          {
            var relay = machinery.LookupRelayByName(relayname);
            var status = new JsonObject();
            status.Add("name", relay.Name);
            status.Add("on", relay.On);
            return status;
          });

      config.AddHandler("PUT", "/hw/relays/{relayname}/on", "turn relay on")
        .ReturnsNothing()
        .HandledBy((relayname) =>
          {
            var relay = machinery.LookupRelayByName(relayname);
            relay.On = true;
          });

      config.AddHandler("PUT", "/hw/relays/{relayname}/off", "turn relay off")
        .ReturnsNothing()
        .HandledBy((relayname) =>
          {
            var relay = machinery.LookupRelayByName(relayname);
            relay.On = false;
          });

      config.AddHandler("POST", "/admin/log/clear", "clear the entire log")
        .ReturnsNothing()
        .HandledBy(() =>
          {
            Logger.Instance.Full.Clear();
            Logger.Instance.Errors.Clear();
          });

      config.AddHandler("GET", "/admin/log/full", "get full log")
        .ReturnsStream()
        .HandledBy((context) =>
          {
            context.Response.OutputStream.WriteByte((byte)'[');
            foreach (var line in Logger.Instance.Full.GetLines())
            {
              var b = System.Text.Encoding.UTF8.GetBytes(Json.NETMF.JsonSerializer.SerializeObject(line));
              context.Response.OutputStream.Write(b, 0, b.Length);
              context.Response.OutputStream.WriteByte((byte)',');
            }
            context.Response.OutputStream.WriteByte((byte)']');
          });

      config.AddHandler("GET", "/admin/log/errors", "get error log")
        .ReturnsJson()
        .HandledBy(() =>
          {
            return Logger.Instance.Errors.GetLinesAsJson();
          });

      config.AddHandler("GET", "/config/schedule", "get the schedule")
        .ReturnsJson()
        .HandledBy(() => doorScheduler.GetScheduleAsJson());

      var credentials = CredentialValidatorFactory.CreateSimpleValidator("Bootstrapper", "admin", "hnsefyk");
      var webService = new WebService(c_servicePort, credentials, config);

      string prefix = Name + ": ";
      webService.Logging.OnLogInfo += message => Logger.Instance.LogInfo(prefix + message);
      webService.Logging.OnLogError += message => Logger.Instance.LogError(prefix + message);
      webService.Logging.OnLogException += (message, ex) => Logger.Instance.LogException(prefix + message, ex);

      webService.Start();
    }
    public JsonObject GetApiDocs(string apiname)
    {
      string slashApiName = "/" + apiname;
      if (!_apis.Contains(slashApiName))
        throw new Exception("No documentation for API " + slashApiName);

      var apidoc = new JsonObject();
      apidoc.Add("swaggerVersion", "1.2");
      apidoc.Add("apiVersion", "1.0.0"); // todo
      apidoc.Add("basePath", _apiBasePath);
      apidoc.Add("resourcePath", slashApiName);
      var produces = new ArrayList();

      // todo: specify ContentType of return value
      produces.Add("application/json");
      produces.Add("application/xml");
      produces.Add("text/plain");
      produces.Add("text/html");
     


      apidoc.Add("produces", produces);
      apidoc.Add("description", ""); // todo
      var apis = new ArrayList();
      foreach (RestHandler m in (_apis[slashApiName] as ArrayList))
      {
        var api = new Hashtable();
        api.Add("path", m.Path.Substring(_apiBasePath.Length)); // todo better
        var operations = new ArrayList(); // todo: collect operations on same url, eg GET/PUT /something
        var operation = new Hashtable();
        operation.Add("method", m.Method);
        operation.Add("nickname", m.Path);//BuildNickname(m.Path)); // todo
        if (m.Notes != null)
          operation.Add("notes", m.Notes);
        var parameters = new ArrayList();
        foreach (var argName in m.ArgNames)
        {
          var param = new Hashtable();
          param.Add("description", "description");// todo
          param.Add("name", argName);
          param.Add("paramType", "path"); // todo, deduce from path/query
          param.Add("required", true); // all params are required
          param.Add("type", "string"); // all params are strings
          parameters.Add(param);
        }
        if (parameters.Count > 0)
          operation.Add("parameters", parameters);

        operation.Add("summary", m.Summary);
        operation.Add("type", "string"); //todo
        operations.Add(operation);
        api.Add("operations", operations);
        apis.Add(api);
      }
      apidoc.Add("apis", apis);
      return apidoc;
    }
 public JsonObject GetApiResourceListing()
 {
   var resourceListing = new JsonObject();
   resourceListing.Add("swaggerVersion", "1.2");
   resourceListing.Add("apiVersion", "1.0.0"); // todo
   var apis = new ArrayList();
   foreach (string apiName in _apis.Keys)
   {
     var api = new Hashtable();
     api.Add("path", apiName);
     api.Add("description", ""); // todo
     apis.Add(api);
   }
   resourceListing.Add("apis", apis);
   return resourceListing;
 }
 private void SendResponseWithError(HttpListenerResponse response, HttpStatusCode status, string errorMessage)
 {
   errorMessage = Util.Utils.RemoveNewlines(errorMessage);
   Logger.Instance.LogError(errorMessage);
   var error = new JsonObject();
   error.Add("error", errorMessage);
   var result = Encoding.UTF8.GetBytes(JsonSerializer.SerializeObject(error));
   response.ContentType = "application/json";
   response.StatusCode = (int)status;
   response.ContentLength64 = result.Length;
   response.OutputStream.Write(result, 0, result.Length);
 }
 internal JsonObject GetScheduleAsJson()
 {
   var schedule = new JsonObject();
   lock (_nextEventLock)
   {
     schedule.Add("nextevent", _nextEventIsEvening ? "evening" : "morning");
     schedule.Add("time", _nextEventTime);
     schedule.Add("remainingInSec", (_nextEventTime - DateTime.Now).Ticks / TimeSpan.TicksPerSecond);
   }
   return schedule;
 }