{"id":24953890,"url":"https://github.com/daggilli/raspberryql","last_synced_at":"2026-05-09T10:36:59.348Z","repository":{"id":273397599,"uuid":"919592051","full_name":"daggilli/raspberryql","owner":"daggilli","description":"A simple, extensible Apollo/GraphQL server to interface with a Raspberry Pi.","archived":false,"fork":false,"pushed_at":"2025-01-24T15:14:46.000Z","size":70,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-03T04:16:12.513Z","etag":null,"topics":["apollo","apollo-server","graphql","raspberry-pi","raspberry-pi-gpio","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daggilli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-20T17:13:11.000Z","updated_at":"2025-01-24T15:14:50.000Z","dependencies_parsed_at":"2025-01-20T17:56:25.557Z","dependency_job_id":null,"html_url":"https://github.com/daggilli/raspberryql","commit_stats":null,"previous_names":["daggilli/raspberryql"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daggilli%2Fraspberryql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daggilli%2Fraspberryql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daggilli%2Fraspberryql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daggilli%2Fraspberryql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daggilli","download_url":"https://codeload.github.com/daggilli/raspberryql/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246093111,"owners_count":20722395,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apollo","apollo-server","graphql","raspberry-pi","raspberry-pi-gpio","typescript"],"created_at":"2025-02-03T04:16:28.819Z","updated_at":"2026-05-09T10:36:59.312Z","avatar_url":"https://github.com/daggilli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RASPBERRYQL #\n### A simple, extensible interface to a Raspberry Pi's GPIO via GraphQL ###\n\nThis project provides basic read and write access to the GPIO pins of a Raspberry Pi via an Apollo GraphQL server.\n\n### Basic Usage ###\nPins must be registered before use. This is handled by the `registerPin` mutation which takes a pin name and a direction (which is an `Enum: IN | OUT`). To set an output pin's state use the `setState` mutation; to read an input pin's state, use the `state` query. A simple example in Python follows (assume a microswitch is connected to pin 17 and an LED to pin 21):\n\n```python\nfrom gql import gql, Client\nfrom gql.transport.aiohttp import AIOHTTPTransport\nfrom graphql import DocumentNode\n\n# Assume pin 17 is connected to a microswitch and pin 21 to an LED\nQUERIES: dict[str, DocumentNode] = {\n    \"register\": gql(\n        \"\"\"\n        mutation registerPin($pinName: String!, $direction: Direction!) {\n            registerPin(pinName: $pinName, direction: $direction)\n        }\n\"\"\"\n    ),\n    \"read_microswitch\": gql(\n        \"\"\"\n        query getState {\n            state(pinName: \"GPIO17\")\n        }\n\"\"\"\n    ),\n    \"led_on\": gql(\n        \"\"\"\n        mutation turnOn {\n            setState(pinName: \"GPIO21\",state: true)\n        }\n\"\"\"\n    ),\n}\n\n\ndef main() -\u003e None:\n    print(\"main\")\n    transport = AIOHTTPTransport(url=\"https://\u003cYour IP here\u003e:4000/\")\n    client = Client(transport=transport, fetch_schema_from_transport=True)\n\n    # set up pins 17 (output) and 21 (input)\n    client.execute(\n        QUERIES[\"register\"], variable_values={\"pinName\": \"GPIO21\", \"direction\": \"OUT\"}\n    )\n\n    client.execute(\n        QUERIES[\"register\"], variable_values={\"pinName\": \"GPIO17\", \"direction\": \"IN\"}\n    )\n\n    # read the state of the microswitch. Depending on whether # it is pulled up or down, True and False will represent open and closed (or vice versa) \n    result = client.execute(QUERIES[\"read_microswitch\"])\n    print(result)\n\n    # turn the LED on\n    result = client.execute(QUERIES[\"led_on\"])\n    print(result)\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Configuration ###\n\nThere are two main configuration files, one mandatory (the server configuration) and the other optional (default pin registrations). Both are to be found in the `config` top-level directory.\n\nThe server configuration file is named `config.json`. It has three fields, thus:\n\n```json\n{\n  \"expressPort\": \u003cinteger, the port where the server listens\u003e,\n  \"sslKeyPath\": \u003cstring, path to the server's SSL key file\u003e,\n  \"sslCertificatePath\": \u003cstring, path to the server's SSL certificate file\u003e\n}\n```\n\nThe pin registrations file is named `defaultPins.json`. It consists of an array of pin names and directions of pins that should be pre-registered at startup, thus:\n\n```json\n[\n  {\n    \"pinName\": \"GPIOxx\",\n    \"direction\": \"out\"\n  },\n  {\n    \"pinName\": \"GPIOyy\",\n    \"direction\": \"in\"\n  }\n]\n```\nwhere `GPIOxx` etc are pin names such as `GPIO13`.\n\n### Notes ###\n\nThe server is written in TypeScript and uses version 4 of the Apollo software. It was written on a Raspberry Pi 4 Model B+ with 8 GB of RAM, running Raspberry Pi OS 12 (which is essentially Debian 12 Bookworm).\n\nThe server is not particularly fast, as the underlying transport is usually HTTP and each query or mutation necessitates a round trip. You can probably expect a maximum of about 50 calls per second. It is primarily designed for slowly-varying insrumtation like, say, a weather station. The initial reason for creating the project was to provide a simple backend to a React app running on the Pi to read and write to the GPIO.\n\nThe project uses the `onoff` node package to communicate with the Pi. Recent changes in how the GPIO is accessed from user space mean that standard pin numbers (whether Broadcom or WiringPi) do not work as is. I have created a simple class, `PinMapper`, that lazily reads kernel debug info to obtain the canonical pin number (for example, `GPIO5` might correspond to `gpio-517` and it is this number, 517, that `onoff` is expecting). The server expects queries to use the normal `GPIOxx` pin names.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaggilli%2Fraspberryql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaggilli%2Fraspberryql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaggilli%2Fraspberryql/lists"}