{"id":23461351,"url":"https://github.com/hhromic/libe131","last_synced_at":"2025-10-12T15:31:03.799Z","repository":{"id":69929906,"uuid":"65633518","full_name":"hhromic/libe131","owner":"hhromic","description":"libE131: a lightweight C/C++ library for the E1.31 (sACN) protocol","archived":false,"fork":false,"pushed_at":"2024-07-31T22:55:38.000Z","size":58,"stargazers_count":81,"open_issues_count":3,"forks_count":21,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-01-22T04:07:03.315Z","etag":null,"topics":["c","cpp","e131","library","light-controller","lightweight","protocol","sacn"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hhromic.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":"2016-08-13T19:28:54.000Z","updated_at":"2025-01-20T05:13:39.000Z","dependencies_parsed_at":"2024-03-12T18:54:53.795Z","dependency_job_id":"cc0c2cc1-ad43-4f85-b8b9-b43ff3d6c22b","html_url":"https://github.com/hhromic/libe131","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hhromic%2Flibe131","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hhromic%2Flibe131/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hhromic%2Flibe131/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hhromic%2Flibe131/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hhromic","download_url":"https://codeload.github.com/hhromic/libe131/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236130950,"owners_count":19099713,"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":["c","cpp","e131","library","light-controller","lightweight","protocol","sacn"],"created_at":"2024-12-24T07:34:40.101Z","updated_at":"2025-10-12T15:31:03.451Z","avatar_url":"https://github.com/hhromic.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libE131: a lightweight C/C++ library for the E1.31 (sACN) protocol\n\nThis is a lightweight C/C++ library that provides a simple API for packet, client and server programming to be used for communicating with devices implementing the E1.31 (sACN) protocol. Detailed information about E.131 (sACN) can be found on this [Wiki article](https://www.doityourselfchristmas.com/wiki/index.php?title=E1.31_%28Streaming-ACN%29_Protocol) from which most informational content about E1.31 in this document comes from.\n\nACN is a suite of protocols (via Ethernet) that is the industry standard for lighting and control. ESTA, the creator of the standard, ratified a subset of this protocol for \"lightweight\" devices which is called sACN (E1.31). This lightweight version allows microcontroller based lighting equipment to communicate via ethernet, without all the overhead of the full ACN protocol.\n\nThe simplest way to think about E1.31 is that it is a way to transport a large number of lighting control channels over a traditional ethernet network connection. E1.31 transports those channels in \"Universes\", which is a collection of up to 512 channels together. E.131 is ethernet based and is the data sent via UDP. The two accepted transport methods are multicast and unicast, the most common implementation is multicast. When using multicast all the controller needs to do is subscribe to the multicast address for the universe that you want to receive data from.\n\n## Installation\n\nTo install libE131 in your system, download the [latest release archive](https://github.com/hhromic/libe131/releases/latest) and use the standard autotools approach:\n```\n./configure --prefix=/usr \\\n\u0026\u0026 make \\\n\u0026\u0026 sudo make install\n```\n\nThe last step requires `root` privileges. You can uninstall the library using:\n```\nsudo make uninstall\n```\n    \nA development package for Arch Linux is also available on the [AUR](https://aur.archlinux.org/packages/libe131-git/).\n\n## E1.31 (sACN) Packets\n\nE1.31 network packets are based on ACN and are composed of three layers:\n```\nE1.31 Packet = ACN Root Layer + Framing Layer + Device Management Protocol (DMP) Layer\n```\n\nAll packet contents are transmitted in **network byte order (big endian)**. If you are accessing fields larger than one byte, you must read/write from/to them using the `ntohs`, `ntohl`, `htons` and `htonl` conversion functions.\n\nFortunately, most of the time you will not need to manipulate those fields directly because libE131 provides convenience functions for the most common fields. See the API documentation section for more information.\n\nThe following is the `e131_packet_t` type union provided by libE131 for sending/receiving E1.31 packets:\n```c\ntypedef union {\n  PACK(struct {\n    PACK(struct { /* ACN Root Layer: 38 bytes */\n      uint16_t preamble_size;    /* Preamble Size */\n      uint16_t postamble_size;   /* Post-amble Size */\n      uint8_t  acn_pid[12];      /* ACN Packet Identifier */\n      uint16_t flength;          /* Flags (high 4 bits) \u0026 Length (low 12 bits) */\n      uint32_t vector;           /* Layer Vector */\n      uint8_t  cid[16];          /* Component Identifier (UUID) */\n    }) root;\n\n    PACK(struct { /* Framing Layer: 77 bytes */\n      uint16_t flength;          /* Flags (high 4 bits) \u0026 Length (low 12 bits) */\n      uint32_t vector;           /* Layer Vector */\n      uint8_t  source_name[64];  /* User Assigned Name of Source (UTF-8) */\n      uint8_t  priority;         /* Packet Priority (0-200, default 100) */\n      uint16_t reserved;         /* Reserved (should be always 0) */\n      uint8_t  seq_number;       /* Sequence Number (detect duplicates or out of order packets) */\n      uint8_t  options;          /* Options Flags (bit 7: preview data, bit 6: stream terminated) */\n      uint16_t universe;         /* DMX Universe Number */\n    }) frame;\n\n    PACK(struct { /* Device Management Protocol (DMP) Layer: 523 bytes */\n      uint16_t flength;          /* Flags (high 4 bits) / Length (low 12 bits) */\n      uint8_t  vector;           /* Layer Vector */\n      uint8_t  type;             /* Address Type \u0026 Data Type */\n      uint16_t first_addr;       /* First Property Address */\n      uint16_t addr_inc;         /* Address Increment */\n      uint16_t prop_val_cnt;     /* Property Value Count (1 + number of slots) */\n      uint8_t  prop_val[513];    /* Property Values (DMX start code + slots data) */\n    }) dmp;\n  });\n\n  uint8_t raw[638]; /* raw buffer view: 638 bytes */\n} e131_packet_t;\n```\n\nThis union provides two ways to access the data of an E1.31 packet:\n\n1. Directly using the `raw` member (typically used for receiving data from the network).\n2. Structurally using the `root`, `frame` and `dmp` members (typically used for processing a packet).\n\nYou can easily create and initialize a new E1.31 packet to be used for sending using the `e131_pkt_init()` function.\n\nRefer to the [examples](#examples) section for how to use this data structure with libE131.\n\n### Framing Layer Options\n\nThe library provides two convenience functions, `e131_get_option()` and `e131_set_option()` to manipulate the options flag in the Framing Layer of an E1.31 packet. The following table describes the available option constants:\n\n| Option Constant | Description |\n|:----------------|:------------|\n| `E131_OPT_TERMINATED` | The current packet is the last one in the stream. The receiver should stop processing further packets. |\n| `E131_OPT_PREVIEW` | The data in the packet should be only used for preview purposes, e.g. console display, and not to drive live fixtures. |\n\nRefer to the [examples](#examples) section for how to use Framing Layer options with libE131.\n\n### Packet Validation\n\nThe library provides a convenience function, `e131_pkt_validate()`, to check if an E1.31 packet is valid to be processed by your application. This function returns a validation status from the `e131_error_t` enumeration. The following table describes the available error constants:\n\n| Error Constant | Description |\n|:---------------|:------------|\n| `E131_ERR_NONE` | Success (no validation error detected, you can process the packet). |\n| `E131_ERR_PREAMBLE_SIZE` | Invalid Preamble Size. |\n| `E131_ERR_POSTAMBLE_SIZE` | Invalid Post-amble Size. |\n| `E131_ERR_ACN_PID` | Invalid ACN Packet Identifier. |\n| `E131_ERR_VECTOR_ROOT` | Invalid Root Layer Vector. |\n| `E131_ERR_VECTOR_FRAME` | Invalid Framing Layer Vector. |\n| `E131_ERR_VECTOR_DMP` | Invalid Device Management Protocol (DMP) Layer Vector. |\n| `E131_ERR_TYPE_DMP` | Invalid DMP Address \u0026 Data Type. |\n| `E131_ERR_FIRST_ADDR_DMP` | Invalid DMP First Address. |\n| `E131_ERR_ADDR_INC_DMP` | Invalid DMP Address Increment. |\n\nThe above error descriptions are also programatically obtainable using the `e131_strerror()` function. Refer to the [API documentation](#api-documentation) section for more information.\n\nRefer to the [examples](#examples) section for how to use packet validation and error reporting with libE131.\n\n## Unicast and Multicast Destinations\n\nMost E1.31 software and hardware can be set up to communicate via two transport methods: **Unicast** and **Multicast**.\n\n### Unicast Transmission\n\nUnicast is a method of sending data across a network where two devices, the control PC and the lighting controller, are directly connected (or through a network switch or router) and the channel control information meant for that specific controller is only sent to that controller. Unicast is a **point to point protocol** and the lighting channel information is only switched or routed to the device with the matching IP address.\n\nYou must have unique IP address in each controller. Using Unicast the data packets are sent directly to the device instead of being broadcast across the entire subnet.\n\nIn unicast transmission:\n\n* More channels of data are allowed to controllers and bridges (commonly 12 Universes vs. 7 for Multicast).\n* Channels can only be sent to one controller per Universe.\n\n### Multicast Transmission\n\nMulticast is a method to send data across a network where a sender, typically a PC, broadcasts the data to all devices connected to the network subnet and the information about the channels are sent to all controllers connected to the network and every other device on the network.\n\nMulticast is a **point to multipoint broadcast** where the controllers need to listen to and only respond to information they are configured to use. Your PC sequencing software or streaming tool sends multicast packets with an address of `239.255.\u003cUHB\u003e.\u003cULB\u003e` where `UHB` is the Universe high byte and `LHB` is the Universe low byte. As an example, the address for universe `1` would be `239.255.0.1`. This is why using multicast addressing can be simpler to configure since this address is always the same for any device using that universe.\n\nDepending on the device and the number of universes of data sent it can swamp the device and possibly end up causing a loss of data. Note however that this is not an issue for most networks until you get into the dozens of universes so it's not an issue for most users.\n\nThe data is received on multicast IP address not on the individual device IP address.\n\nIn multicast transmission:\n\n* Less channels of data are allowed to controllers and bridges (commonly 7 Universes vs. 12 for Unicast).\n* Simpler network configuration since controllers don't need data address information.\n* Channels can be mirrored on multiple controllers since the same Universe can be used by multiple controllers.\n\n## E1.31 (sACN) Universes\n\nE1.31 transports lighting information in \"Universes\", which is a collection of up to 512 channels together. You can chose any universe number from **1-63999** and assign it to a block of channels in your sequencing software. While a Universe can contain up to 512 channels, it does not have to, and can be any number between 1-512 channels.\n\n## API Documentation\n\n### Public Library Constants\n\n* *const uint16_t* `E131_DEFAULT_PORT`: default network port for E1.31 UDP data (5568).\n* *const uint8_t* `E131_DEFAULT_PRIORITY`: default E1.31 packet priority (100).\n\n### Public Library Functions\n\nThe library provides a number of functions to help you develop clients and servers that communicate using the E1.31 protocol. The following is a descriptive list of all functions provided.\n\nSee the examples sections to see how the most common API functions are used with libE131.\n\n* `int e131_socket(void)`: Create a socket file descriptor suitable for E1.31 communication. On success, a file descriptor for the new socket is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_bind(int sockfd, const uint16_t port)`: Bind a socket file descriptor to a port number for E1.31 communication. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_unicast_dest(e131_addr_t *dest, const char *host, const uint16_t port)`: Initialize a unicast E1.31 destination using a host and port number. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_multicast_dest(e131_addr_t *dest, const uint16_t universe, const uint16_t port)`: Initialize a multicast E1.31 destination using a universe and port number. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_dest_str(char *str, const e131_addr_t *dest)`: Describe an E1.31 destination into a string (must be at least 22 bytes). On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_multicast_iface(int sockfd, const int ifindex)`: Configure a socket file descriptor to use a specific network interface for outgoing multicast data. Interface index zero is the system default interface. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_multicast_join(int sockfd, const uint16_t universe)`: Join a socket file descriptor to an E1.31 multicast group using a universe. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_multicast_join_iface(int sockfd, const uint16_t universe, const int ifindex)`: Join a socket file descriptor to an E1.31 multicast group using a universe and a specific network interface. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_multicast_join_ifaddr(int sockfd, const uint16_t universe, const char *ifaddr)`: Join a socket file descriptor to an E1.31 multicast group using a universe and an IP address to bind to. On error, -1 is returned, and `errno` is set appropriately.\n\n* `int e131_pkt_init(e131_packet_t *packet, const uint16_t universe, const uint16_t num_slots)`:  Initialize an E1.31 packet using a universe and a number of slots. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `bool e131_get_option(const e131_packet_t *packet, const e131_option_t option)`: Get the state of a framing option in an E1.31 packet.\n\n* `int e131_set_option(e131_packet_t *packet, const e131_option_t option, const bool state)`: Set the state of a framing option in an E1.31 packet. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `ssize_t e131_send(int sockfd, const e131_packet_t *packet, const e131_addr_t *dest)`: Send an E1.31 packet to a socket file descriptor using a destination. On success, the number of bytes sent is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `ssize_t e131_recv(int sockfd, e131_packet_t *packet)`: Receive an E1.31 packet from a socket file descriptor. This function returns the number of bytes received, or -1 if an error occurred. On error, `errno` is set appropriately.\n\n* `e131_error_t e131_pkt_validate(const e131_packet_t *packet)`: Validate that an E1.31 packet is well-formed. See the Packet Validation section.\n\n* `bool e131_pkt_discard(const e131_packet_t *packet, const uint8_t last_seq_number)`: Check if an E1.31 packet should be discarded (sequence number out of order). This function uses the standard out-of-sequence detection algorithm defined in the E1.31 specification.\n\n* `int e131_pkt_dump(FILE *stream, const e131_packet_t *packet)`: Dump an E1.31 packet to a stream (i.e. stdout, stderr). The output is formatted for human readable output. On success, zero is returned. On error, -1 is returned, and `errno` is set appropriately.\n\n* `const char *e131_strdest(const e131_addr_t *dest)`: Return a string describing an E1.31 destination.\n\n* `const char *e131_strerror(const e131_error_t error)`: Return a string describing an E1.31 error.\n\n## Examples\n\nThe [`examples/test_client.c`](examples/test_client.c) example demonstrates how to create a simple E1.31 client. To compile it:\n```\ngcc -Wall test_client.c -o test_client -le131\n```\n\nThe [`examples/test_server.c`](examples/test_server.c) example demonstrates how to create a simple E1.31 server. To compile it:\n```\ngcc -Wall test_server.c -o test_server -le131\n```\n\n## Projects using libE131\n\nThe following projects use libE131:\n\n* [E1.31 Xterm256 Console Viewer](https://github.com/hhromic/e131-viewer)\n* [E1.31 to AdaLight Bridge](https://github.com/hhromic/e131-adalight-bridge)\n* [E1.31 to MQTT Bridge](https://github.com/hhromic/e131-mqtt-bridge)\n* [MIDI to E1.31 Light Synthesizer](https://github.com/hhromic/midi-e131-synth)\n\nAlso check out the [Node.js port](https://github.com/hhromic/e131-node) of libE131.\n\n## License\n\nThis software is under the **Apache License 2.0**.\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhhromic%2Flibe131","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhhromic%2Flibe131","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhhromic%2Flibe131/lists"}