#ansi #dmx #acn #sacn #e131

no-std sacn-unofficial

来自https://github.com/RustLight/sacn的非官方sACN实现镜像

1个不稳定版本

使用旧的Rust 2015

0.9.0 2020年11月30日

#13 in #dmx

每月35次下载

MIT/Apache

5MB
3.5K SLoC

RUST Sacn

ANSI E1.31 Streaming ACN协议的Rust实现,经过ANSI E1.31-2018协议版本的测试。

支持

  • 使用ANSI E1.31-2018协议在IPv4和IPv6上发送和接收数据
  • 支持单播、多播和广播
  • 在Windows和Linux上测试过
  • 宇宙同步
  • 宇宙发现

最初从https://github.com/lschmierer/sacn分叉,然后在圣安德鲁斯大学本科毕业设计项目中进一步开发。

待办事项:分发文档(安装、测试等)

安装

先决条件

入门指南

合规性

ANSI E1.31-2018协议的合规性已测试(2020年4月),结果显示在https://github.com/Lan2u/RustSacn/blob/master/documentation/ANSI-E1.31-2018-Compliance-Check-List.pdf

测试

演示实现


lib.rs:

实现sACN网络协议。

此crate实现了ANSI E1.31-2018中指定的Streaming ACN (sACN)网络协议。Streaming ACN建立在ACN协议套件(ANSI E1.17-2015)之上,与之兼容。此库支持发送和接收数据,宇宙同步和宇宙发现。此库支持linux(完全)和windows(不支持接收多播)以及IP单播、多播和广播。

安装说明详细见README文件。

此文件作为圣安德鲁斯大学计算机科学BSC荣誉学位论文项目的一部分进行了修改。

示例

创建一个sACN接收器并接收数据。这会自动处理在正确的时间接收同步数据,接收到的数据数组包含所有应该同时处理的全部数据(因此如果有2个同步数据包,数组长度将是2)。

use sacn::receive::SacnReceiver;
use sacn::packet::ACN_SDT_MULTICAST_PORT;

use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::time::Duration;

const UNIVERSE1: u16 = 1;
const TIMEOUT: Option<Duration> = Some(Duration::from_secs(1)); // A timeout of None means blocking behaviour, some indicates the actual timeout.

let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), ACN_SDT_MULTICAST_PORT);

let mut dmx_rcv = SacnReceiver::with_ip(addr, None).unwrap();

dmx_rcv.listen_universes(&[UNIVERSE1]).unwrap();

// .recv(TIMEOUT) handles processing synchronised as-well as normal data.
match dmx_rcv.recv(TIMEOUT) {
    Err(e) => {
        // Print out the error.
        println!("{:?}", e);
    }
    Ok(p) => {
        // Print out the data.
        println!("{:?}", p);
    }
}

创建一个sACN接收器并通过宇宙发现检查已发现的源。

use sacn::receive::SacnReceiver;
use sacn::packet::ACN_SDT_MULTICAST_PORT;

use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::time::Duration;

const TIMEOUT: Option<Duration> = Some(Duration::from_secs(1)); // A timeout of None means blocking behaviour, some indicates the actual timeout.

let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), ACN_SDT_MULTICAST_PORT);

// Creating the receiver, automatically listens for universe discovery packets.
let mut dmx_rcv = SacnReceiver::with_ip(addr, None).unwrap();

// Cause source discovery to be announced by a returned error. If this isn't true then discovery packets are still handled by the user must poll
// the discovered sources list periodically as there will be no announcement that a discovery packet has been processed. By default this option is
// off (false) based on the assumption that when receiving data the majority of the time the receiver just wants to process more data from the same
// universe and doesn't want to discover sources.
dmx_rcv.set_announce_source_discovery(true);

// Receive for a short period, no data is expected but this allows universe discovery packets to be received.
// This example will always timeout if run in isolation as there are no sources running on the network. 
match dmx_rcv.recv(TIMEOUT) {
    Err(e) => {
        match e.kind() {
            sacn::error::errors::ErrorKind::SourceDiscovered(source_name) => {
                println!("Source name: {} discovered!", source_name);    
            }
            other => {
                // Print out the error.
                println!("{:?}", other);
            }
        }
    }
    Ok(p) => {
        // Print out the data. Note that no data is expected as no universes are registered for receiving data.
        println!("{:?}", p);
    }
}

创建一个sACN发送器并发送一些未同步数据。sACNSender会自动发送宇宙发现数据包。

use sacn::source::SacnSource;
use sacn::packet::ACN_SDT_MULTICAST_PORT;
use std::net::{IpAddr, SocketAddr};

let local_addr: SocketAddr = SocketAddr::new(IpAddr::V4("0.0.0.0".parse().unwrap()), ACN_SDT_MULTICAST_PORT + 1);

let mut src = SacnSource::with_ip("Source", local_addr).unwrap();

let universe: u16 = 1;                        // Universe the data is to be sent on.
let sync_uni: Option<u16> = None;             // Don't want the packet to be delayed on the receiver awaiting synchronisation.
let priority: u8 = 100;                       // The priority for the sending data, must be 1-200 inclusive,  None means use default.
let dst_ip: Option<SocketAddr> = None;        // Sending the data using IP multicast so don't have a destination IP.

src.register_universe(universe).unwrap(); // Register with the source that will be sending on the given universe.

let mut data: Vec<u8> = vec![0, 0, 0, 0, 255, 255, 128, 128]; // Some arbitrary data, must have length <= 513 (including start-code).

src.send(&[universe], &data, Some(priority), dst_ip, sync_uni).unwrap(); // Actually send the data

创建一个sACN发送器并发送一些同步数据。

use sacn::source::SacnSource;
use sacn::packet::ACN_SDT_MULTICAST_PORT;

use std::net::{IpAddr, SocketAddr};
use std::thread::sleep;
use std::time::Duration;

let local_addr: SocketAddr = SocketAddr::new(IpAddr::V4("0.0.0.0".parse().unwrap()), ACN_SDT_MULTICAST_PORT + 1);

let mut src = SacnSource::with_ip("Source", local_addr).unwrap();

let universe: u16 = 1;                        // Universe the data is to be sent on.
let sync_uni: Option<u16> = Some(1);          // Data packets use a synchronisation address of 1.
let priority: u8 = 100;                       // The priority for the sending data, must be 1-200 inclusive,  None means use default.
let dst_ip: Option<SocketAddr> = None;        // Sending the data using IP multicast so don't have a destination IP.

src.register_universe(universe).unwrap(); // Register with the source that will be sending on the given universe.

let mut data: Vec<u8> = vec![0, 0, 0, 0, 255, 255, 128, 128]; // Some arbitrary data, must have length <= 513 (including start-code).

// Actually send the data, since the sync_uni is not 0 the data will be synchronised at the receiver (if the receiver supports synchronisation).
src.send(&[universe], &data, Some(priority), dst_ip, sync_uni).unwrap();

// A small delay between sending data and sending the sync packet as recommend in ANSI E1.31-2018 Section 11.2.2.
sleep(Duration::from_millis(10));

// To actually trigger the data need to send a synchronisation packet like so.
src.send_sync_packet(sync_uni.unwrap(), dst_ip).unwrap();

创建一个sACN发送器并使用单播发送数据。

use sacn::source::SacnSource;
use sacn::packet::ACN_SDT_MULTICAST_PORT;

use std::net::{IpAddr, SocketAddr};
use std::thread::sleep;
use std::time::Duration;

let local_addr: SocketAddr = SocketAddr::new(IpAddr::V4("0.0.0.0".parse().unwrap()), ACN_SDT_MULTICAST_PORT + 1);

let mut src = SacnSource::with_ip("Source", local_addr).unwrap();

let universe: u16 = 1;                        // Universe the data is to be sent on.
let sync_uni: Option<u16> = None;             // Data packets are unsynchronised in this example but unicast transmission supports synchronised and unsynchronised sending.
let priority: Option<u8> = Some(100);                       // The priority for the sending data, must be 1-200 inclusive,  None means use default.

// To send using unicast the dst_ip argument is set to a Some() value with the address to send the data to. By default the port should be the
// ACN_SDT_MULTICAST_PORT but this can be configured differently if required in a specific situation. Change this address to the correct address for your
// application, 192.168.0.1 is just a stand-in.
let destination_address: SocketAddr = SocketAddr::new(IpAddr::V4("192.168.0.1".parse().unwrap()), ACN_SDT_MULTICAST_PORT);
let dst_ip: Option<SocketAddr> = Some(destination_address);

src.register_universe(universe).unwrap(); // Register with the source that will be sending on the given universe.

let mut data: Vec<u8> = vec![0, 0, 0, 0, 255, 255, 128, 128]; // Some arbitrary data, must have length <= 513 (including start-code).

// Actually send the data, since the sync_uni is not 0 the data will be synchronised at the receiver (if the receiver supports synchronisation).
src.send(&[universe], &data, priority, dst_ip, sync_uni).unwrap();

依赖项

~3.5–5MB
~94K SLoC