// Copyright (C)2016-2024, Philip Munts dba Munts Technologies. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. using System; using System.Net; using org.acplt.oncrpc; namespace GPIO { /// /// This enumeration type encapsulates GPIO data direction configuration values. /// public enum Direction { /// /// Configure GPIO pin data direction as input. /// Input, /// /// Configure GPIO pin data direction as output. /// Output } /// /// This exception will be raised upon any error encountered while communicating with the ONC/RPC server. /// public class Exception : System.Exception { /// /// Default constructor without parameters. /// public Exception() : base() { } /// /// Constructor including an error message string /// /// Error message public Exception(string message) : base(message) { } } /// /// This class encapsulates a connection to a single MuntsOS ONC/RPC GPIO server. /// public class Server { private gpio_server_oncrpcClient server = null; /// /// Open a connection to a ONC/RPC GPIO server. /// /// Server domain name or IP address. public Server(String servername) { IPAddress serveraddress; // Check for invalid parameter if (Uri.CheckHostName(servername) == UriHostNameType.Unknown) { throw new Exception("GPIO server name is invalid"); } // Resolve the server IP address try { serveraddress = Dns.GetHostAddresses(servername)[0]; } catch { throw new Exception("GPIO server name cannot be resolved"); } try { // Create RPC client object server = new gpio_server_oncrpcClient(serveraddress, OncRpcProtocols.ONCRPC_UDP); // Reduce timeout to 2 seconds OncRpcUdpClient c = (OncRpcUdpClient)server.GetClient(); c.setTimeout(2000); c.setRetransmissionTimeout(500); } catch { throw new Exception("GPIO server handle failed"); } } /// /// This factory method configures the specified GPIO pin and returns a Pin object for it. /// /// GPIO pin number. /// GPIO pin direction, GPIO.Direction.Input or GPIO.Direction.Output. /// GPIO output pin initial state, true or false. Ignored for input pin. /// Returns a configured GPIO Pin object. public Pin OpenPin(int number, Direction direction, bool state = false) { int status; try { status = server.gpio_open_1(number, (int) direction, state ? 1 : 0); } catch { throw new Exception("RPC gpio_open_1() failed"); } if (status < 0) { throw new Exception("RPC gpio_open_1() returned error " + status.ToString()); } try { return new Pin(this.server, number); } catch { throw new Exception("Failed to construct Pin object"); } } } /// /// This class encapsulates a single GPIO pin. /// public class Pin { private gpio_server_oncrpcClient server = null; private int number; /// /// GPIO pin object constructor. /// /// ONC/RPC server handle. /// GPIO pin number. /// /// Do not call this constructor directly; use the Server.OpenPin() factory method instead. /// public Pin(gpio_server_oncrpcClient server, int number) { this.server = server; this.number = number; } /// /// Pin object destructor /// ~Pin() { try { server.gpio_close_1(this.number); } catch { } } /// /// This read/write property reflects the state of the GPIO pin. /// /// /// Allowed values are true or false. /// /// /// Writing to a pin configured for input has no effect. /// public bool state { get { int status; try { status = server.gpio_read_1(this.number); } catch { throw new Exception("RPC gpio_read_1() failed"); } if (status < 0) { throw new Exception("RPC gpio_read_1() returned error " + status.ToString()); } if (status > 1) { throw new Exception("Invalid state value"); } return status == 1; } set { int status; try { status = server.gpio_write_1(this.number, value ? 1 : 0); } catch { throw new Exception("RPC gpio_write_1() failed"); } if (status < 0) { throw new Exception("RPC gpio_write_1() returned error " + status.ToString()); } } } } }