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 void Start() { Logger.Instance.LogInfo("MainController start"); // All background tasks are maintained by the TaskRunner var tasks = new TaskRunner(); // Make sure the RTC is correct tasks.RunForever("RTC", KeepClockAlive); // Create and start the machinery. Init will block until it is completely ready. var machinery = new Machinery(); machinery.Start(); tasks.RunForever("Machinery Sequencer", machinery.Sequencer.Start); // Blink 3 times to show we're starting up machinery.BlinkLED(300, 300, 300, 300, 300); // Setup manual control of the doors machinery.PushButton.ButtonPressed += (s, e) => { Logger.Instance.LogInfo("PushButton press " + e.PressCount); if (machinery.Sequencer.IsBusy) // ignore button-initiated control if doors are already busy { Logger.Instance.LogInfo("Doors are busy, pushbutton ignored"); return; } var door = e.PressCount == 1 ? machinery.DoorCoop : /*TODO remove for OfflineDoor e.PressCount == 2 ? machinery.DoorYard :*/ null; if (door != null) { machinery.Sequencer.Enqueue(() => { if (door.Status == DoorStatus.Closed) door.OpenCompletely(); else door.CloseCompletely(); }); } }; // Setup the automatic door schedule var doorScheduler = new DoorScheduler(); doorScheduler.Morning += () => machinery.Sequencer.Enqueue(() => { machinery.DoorCoop.OpenCompletely(); }); doorScheduler.Evening += () => machinery.Sequencer.Enqueue(() => { machinery.DoorYard.CloseCompletely(); machinery.DoorCoop.CloseCompletely(); machinery.Power1.On = false; machinery.Power2.On = false; }); tasks.RunForever("Door Schedule", doorScheduler.Start); // TODO: lamp schedule? // TODO: safety thread? // Start the web server var webcontrol = new WebControl(); tasks.RunForever(webcontrol.Name, () => webcontrol.Start(machinery, doorScheduler)); // Blink 3 times fast slowly after a brief pause to show that setup has completed Thread.Sleep(1000); machinery.BlinkLED(100, 300, 100, 300, 100); }