Giter Club home page Giter Club logo

stupidartnet's Introduction

.github/workflows/publish-to-pypi.yml License: MIT

StupidArtnet

(Very) Simple Art-Net implementation in Python (compatible with micro python)

Table of Contents

Installing from github

You can get up and running quickly cloning from github. Run the example file to make sure everything is up to scratch

$ git clone https://github.com/cpvalente/stupidArtnet.git
$ cd stupidArtnet
$ python3 examples/example.py

Installing from Pip

The project is now available in Pip and can be installed with pip install stupidartnet

Receiving Data

You can use the server module to receive Art-Net data

# a StupidArtnetServer can listen to a specific universe
# and return new data to a user defined callback
a = StupidArtnetServer(universe=0, callback_function=test_callback)

# if you prefer, you can also inspect the latest
# received data yourself
buffer = a.get_buffer()

Persistent sending

Usually Artnet devices (and DMX in general) transmit data at a rate of no less than 30Hz. You can do this with StupidArtnet by using its threaded abilities

# TO SEND PERSISTENT SIGNAL YOU CAN START THE THREAD
a.start()

# AND MODIFY THE DATA AS YOU GO
for x in range(100):
	for i in range(packet_size):	# Fill buffer with random stuff
		packet[i] = random.randint(0, 255)
	a.set(packet)
	time.sleep(.2)

# ... REMEMBER TO CLOSE THE THREAD ONCE YOU ARE DONE
a.stop()

Example code

See examples folder inside the package directory

  • Use with Tkinter
  • Send Art-Net (client)
  • Receive Art-Net (server)

Notes

Artnet libraries tend to be complicated and hard to get off the ground. Sources were either too simple and didn't explain the workings or become too complex by fully implementing the protocol.
This is meant as an implementation focusing on DMX over Artnet only (ArtDMX).

I am also doing my best to comment the sections where the packets is build. In an effort to help you understand the protocol and be able to extend it for a more case specific use.

Users looking to send a few channels to control a couple of LEDs, projectors or media servers can use this as reference.

Are you running several universes with different fixture types? I would recommend ArtnetLibs or the Python Wrapper for Artnet Libs

Art-Net

Getting things running with protocol is pretty simple. just shove the protocol header into your data array and send it to the right place. Usually Artnet devices are in the range of 2.x.x.x or 10.x.x.x. This is a convention however is not forcefully implemented. I have filled the data to represent a ArtDmx packet

Byte Value Description
0 A Header
1 r "
2 t "
3 - "
4 N "
5 e "
6 t "
7 0x00 "
8 0x00 OpCode Low
9 0x500 OpCode High (ArtDmx)
10 0x00 Protocol V High
11 14 Protocol V Low (currently 14)
12 0x00 Sequence** (0x00 to disable)
13 int 8 Physical
14 int 8 Sub + Uni ***
15 int 8 Net ***
16 int 8 Length High (typically 512)
17 int 8 Length Low
- - Append your packet here

** To allow the receiver to ensure packets are received in the right order
*** By spec should look like this:

Bit 15 Bits 14-8 Bits 7-4 Bits 3-0
0 Net Subnet Universe

Note: This is true for the current version of Artnet 4 (v14), as defined here

Nets and Subnets

Artnet uses the concept of Universes and Subnets for data routing. I simplified here defaulting to use a 256 value universe. This will then be divided into low and high uint8 and look correct either way (Universe 17 will be Universe 1 of Subnet 2). In this case the net will always be 0. This will look correct and behave fine for smaller networks, wanting to be able to specify Universes, Subnets and Nets you can disable simplification and give values as needed.
The spec for Artnet 4 applies here: 128 Nets contain 16 Subnets which contain 16 Universes. 128 * 16 * 16 = 32 768 Universes

# Create a StupidArtnet instance with the relevant values

# By default universe is simplified to a value between 0 - 255
# this should suffice for anything not using subnets
# on sending universe will be masked to two values
# making the use of subnets invisible

universe = 17	# equivalent to universe 1 subnet 1
a = StupidArtnet(target_ip, universe, packet_size)


#############################################

# You can also disable simplification
a.set_simplified(False)

# Add net and subnet value
# Values here are 0 based
a.set_universe(15)
a.set_subnet(15)
a.set_net(127)

License

This project is licensed under the MIT License - see the LICENSE file for details

stupidartnet's People

Contributors

cpvalente avatar deepsourcebot avatar guidoschmidt avatar hugovalente11 avatar isabellelmf avatar kacper516 avatar lukelr avatar rytai avatar stranck avatar vishnumg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

stupidartnet's Issues

Crash on close()

Given that the close() method calls __clock.cancel(), if crashes if a clock was not initialized.

This simple patch is working for me :

diff --git a/lib/StupidArtnet.py b/lib/StupidArtnet.py
index 10b92d8..c26ae22 100644
--- a/lib/StupidArtnet.py
+++ b/lib/StupidArtnet.py
@@ -133,7 +133,10 @@ class StupidArtnet():
 
        def stop(self):
                """Stops thread clock."""
-               self.__clock.cancel()
+               try:
+                       self.__clock.cancel()
+               except:
+                       pass
 
        ##
        # SETTERS - HEADER

def set_16bit(self, address, value) --> wrong put_in_range

line 203 should be

value = self.put_in_range(value, 0, 65535, False)

instead of

value = self.put_in_range(value, 0, 255, False)

It would also be useful to be able to select the HIGH and LOW byte channels,
since every 16 bit DMX/Artnet device handles this different.

On one moving head I have it is like this:
CH1 = PAN_COURSE
CH2 = PAN_FINE

On another one its like this:
CH1 = PAN_COURSE
CH3 = PAN_FINE

Broadcast

Hey there!
Thank you for the great and easy to understand project!
I am wondering, if there is a way to send ArtNet as Broadcast? When using "255.255.255.255" as a destination IP, I will get an error, "Permission denied"

Thanks in advance!

Receive artnet data in python ?

Hello.
First of all thank you for your work, your module works very well!

I’m developing a show control console for a show, and I need to receive artnet data.
I’m desperately looking for a python module that would read artnet data for further processing. Do you know of a module that could help me?
I would also like to know if you are planning to develop a similar module.

Thanks for your help, and have a good day.

Subnets > 0 not working

I'm passing data from Resolume into little program using this library. When I use a universe in subnet 0, there's no issues and I get data printed in the console. If I use a subnet that's greater than 0, I get nothing. I've tried both of the following methods for registering a listener and neither seem to work.

a.register_listener(0, sub=1, net=0, is_simplified=False, callback_function=print)
a.register_listener(16, callback_function=print)

Publish your repo on PyPi for easier installation

Hello! It would be great if you could publish your repo on PyPi. I'm using your library in a project with multiple docker containers and it would be really nice to be able to install it by putting it in the requirements.txt file.

Library not broadcast compatible yet

When sending to a target IP that is a broadcast address following error gets output:
ERROR: Socket error with exception: [Errno 13] Permission denied

This can be resolved with changing the Socket initialisation to:
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

Now to send ArtNet data in broadcast use the broadcast address as target IP (e.g. 2.255.255.255).
To send in Unicast just use a specific address for the target IP.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.