@@ -8,6 +8,7 @@ interface SacnInOptions extends NodeDef {
88 interface ?: string ;
99 port ?: number ;
1010 mode : "htp" | "ltp" | "passthrough" ;
11+ output : "full" | "changes" ;
1112}
1213
1314export interface SacnInMessage extends NodeMessage {
@@ -29,6 +30,10 @@ const nodeInit: NodeInitializer = (RED): void => {
2930 function SacnInNodeConstructor ( this : Node , config : SacnInOptions ) : void {
3031 RED . nodes . createNode ( this , config ) ;
3132
33+ // initialize universe data
34+ let data : Map < number , DMXValues > | undefined = new Map ( ) ;
35+
36+ // parse options for receiver instance
3237 const options : Receiver . Props | MergingReceiver . Props = {
3338 universes : [ config . universe ] ,
3439 reuseAddr : config . reuseAddress !== undefined ? config . reuseAddress : true ,
@@ -40,26 +45,69 @@ const nodeInit: NodeInitializer = (RED): void => {
4045 options . port = config . port ;
4146 }
4247
48+ // internal functions
49+ const getNulledUniverse = ( ) : DMXValues => {
50+ const universe : DMXValues = { } ;
51+
52+ for ( let ch = 1 ; ch <= 512 ; ch ++ ) {
53+ universe [ ch ] = 0 ;
54+ }
55+
56+ return universe ;
57+ } ;
58+
59+ const getReference = ( universe : number ) : DMXValues => {
60+ if ( config . output === "changes" ) {
61+ return { } as DMXValues ;
62+ }
63+
64+ return data ?. get ( universe ) ?? getNulledUniverse ( ) ;
65+ } ;
66+
67+ const parsePayload = ( payload : DMXValues , universe : number ) : DMXValues => {
68+ const processedPayload : DMXValues = getReference ( universe ) ;
69+
70+ Object . keys ( payload ) . forEach ( ( key ) => {
71+ const ch = parseInt ( key , 10 ) ;
72+ processedPayload [ ch + 1 ] = payload [ ch ] ;
73+ } ) ;
74+
75+ if ( config . output !== "changes" ) {
76+ data ?. set ( universe , processedPayload ) ;
77+ }
78+
79+ return processedPayload ;
80+ } ;
81+
82+ // init sacn receiver
4383 let sACN : Receiver ;
44- if ( config . mode === "passthrough" ) {
45- sACN = new Receiver ( options ) ;
46- } else if ( config . mode === "ltp" || config . mode === "htp" ) {
47- ( options as MergingReceiver . Props ) . mode = config . mode . toUpperCase ( ) as "HTP" | "LTP" ;
48- sACN = new MergingReceiver ( options ) ;
49- } else {
50- throw new Error ( "[node-red-sacn] None or invalid mode selected." ) ;
84+ switch ( config . mode ) {
85+ case "passthrough" :
86+ sACN = new Receiver ( options ) ;
87+ break ;
88+ case "htp" :
89+ case "ltp" :
90+ ( options as MergingReceiver . Props ) . mode = config . mode . toUpperCase ( ) as "HTP" | "LTP" ;
91+ sACN = new MergingReceiver ( options ) ;
92+ break ;
93+ default :
94+ throw new Error ( "[node-red-sacn] None or invalid mode selected." ) ;
5195 }
5296
97+ // run cleanup when node is closed
5398 this . on ( "close" , ( ) => {
5499 // close all connections; terminate the receiver
55100 sACN . close ( ) ;
101+
102+ data = new Map ( ) ;
56103 } ) ;
57104
105+ // handle sacn packets
58106 if ( config . mode === "passthrough" ) {
59107 sACN . on ( "packet" , ( packet ) => {
60108 this . send ( {
61109 universe : packet . universe ,
62- payload : incrementPayload ( packet . payload ) ,
110+ payload : parsePayload ( packet . payload , packet . universe ) ,
63111 sequence : packet . sequence ,
64112 source : packet . sourceAddress ,
65113 priority : packet . priority ,
@@ -72,7 +120,7 @@ const nodeInit: NodeInitializer = (RED): void => {
72120 // @ts -expect-error // TODO https://github.com/k-yle/sACN/pull/63
73121 universe : data . universe ,
74122 // @ts -expect-error // TODO https://github.com/k-yle/sACN/pull/63
75- payload : incrementPayload ( data . payload ) ,
123+ payload : parsePayload ( data . payload , data . universe ) ,
76124 } as SacnInMessage ) ;
77125 } ) ;
78126 } else if ( config . mode === "htp" ) {
@@ -82,23 +130,12 @@ const nodeInit: NodeInitializer = (RED): void => {
82130 // @ts -expect-error // TODO https://github.com/k-yle/sACN/pull/63
83131 universe : data . universe ,
84132 // @ts -expect-error // TODO https://github.com/k-yle/sACN/pull/63
85- payload : incrementPayload ( data . payload ) ,
133+ payload : parsePayload ( data . payload , data . universe ) ,
86134 } as SacnInMessage ) ;
87135 } ) ;
88136 }
89137 }
90138
91- function incrementPayload ( payload : DMXValues ) : DMXValues {
92- const result : DMXValues = { } ;
93-
94- Object . keys ( payload ) . forEach ( ( key ) => {
95- const ch = parseInt ( key , 10 ) ;
96- result [ ch + 1 ] = payload [ ch ] ;
97- } ) ;
98-
99- return result ;
100- }
101-
102139 RED . nodes . registerType ( "sacn_in" , SacnInNodeConstructor ) ;
103140} ;
104141
0 commit comments