Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.

Implement an Art-Net service into nodecg-io #257

Merged
merged 4 commits into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ nodecg-io is the successor of [ChatOverflow](https://github.com/codeoverflow-org

## Implemented Services and Interfaces

- AutoHotkey
- Android (using adb)
- ArtNet
- AutoHotkey
- CurseForge
- DBus
- Discord
Expand Down
13 changes: 13 additions & 0 deletions nodecg-io-artnet/artnet-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"host": {
"type": "string",
"description": "The brodcast host, default '0.0.0.0'",
"default": "0.0.0.0"
}
},
"required": []
}
26 changes: 26 additions & 0 deletions nodecg-io-artnet/extension/artnetServiceClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ArtNetController } from "artnet-protocol/dist";
import { ArtDmx } from "artnet-protocol/dist/protocol";
import { ArtNetServiceConfig } from "./index";

export class ArtNetServiceClient extends ArtNetController {
constructor(config: ArtNetServiceConfig) {
super();
this.nameShort = "nodecg-io";
this.nameLong = "https://github.com/codeoverflow-org/nodecg-io";
this.bind(config.host);
}

/**
* Little simplification to receive `dmx` data.
*/
onDMX(listener: (packet: ArtDmx) => void): ArtNetServiceClient {
return this.on("dmx", listener);
}

/**
* Little simplification to send `dmx` data.
*/
public send(universe: number, data: number[]): void {
this.sendBroadcastPacket(new ArtDmx(0, 0, universe, data));
}
}
37 changes: 37 additions & 0 deletions nodecg-io-artnet/extension/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { NodeCG } from "nodecg-types/types/server";
import { Result, emptySuccess, success, ServiceBundle } from "nodecg-io-core";
export { ArtNetServiceClient } from "./artnetServiceClient";
import { ArtNetServiceClient } from "./artnetServiceClient";

export interface ArtNetServiceConfig {
host: string;
port?: number | string;
refresh?: number | string;
iface?: string;
sendAll?: boolean;
}

module.exports = (nodecg: NodeCG) => {
new ArtNetService(nodecg, "artnet", __dirname, "../artnet-schema.json").register();
};

class ArtNetService extends ServiceBundle<ArtNetServiceConfig, ArtNetServiceClient> {
async validateConfig(): Promise<Result<void>> {
return emptySuccess();
}

async createClient(config: ArtNetServiceConfig): Promise<Result<ArtNetServiceClient>> {
const client = new ArtNetServiceClient(config);

return success(client);
}

stopClient(client: ArtNetServiceClient): void {
client.close();
this.nodecg.log.info("Successfully stopped the Art-Net service.");
}

removeHandlers(client: ArtNetServiceClient): void {
client.removeAllListeners();
}
}
47 changes: 47 additions & 0 deletions nodecg-io-artnet/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "nodecg-io-artnet",
"version": "0.2.0",
"description": "Allows you to send DMX512 data over Art-Net™ to to Art-Net nodes i.e. professional lighting fixtures.",
"homepage": "https://nodecg.io/RELEASE/samples/artnet",
"author": {
"name": "Tim-Tech-Dev",
"url": "https://github.com/Tim-Tech-Dev"
},
"repository": {
"type": "git",
"url": "https://github.com/codeoverflow-org/nodecg-io.git",
"directory": "nodecg-io-artnet"
},
"files": [
"**/*.js",
"**/*.js.map",
"**/*.d.ts",
"*.json"
],
"main": "extension/index",
"scripts": {
"build": "tsc -b",
"watch": "tsc -b -w",
"clean": "tsc -b --clean"
},
"keywords": [
"nodecg-io",
"nodecg-bundle"
],
"nodecg": {
"compatibleRange": "^1.1.1",
"bundleDependencies": {
"nodecg-io-core": "^0.2.0"
}
},
"license": "MIT",
"devDependencies": {
"@types/node": "^15.0.2",
"nodecg-types": "^1.8.2",
"typescript": "^4.2.4"
},
"dependencies": {
"nodecg-io-core": "^0.2.0",
"artnet-protocol": "^0.2.1"
}
}
3 changes: 3 additions & 0 deletions nodecg-io-artnet/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../tsconfig.common.json"
}
5 changes: 2 additions & 3 deletions nodecg-io-core/dashboard/bundles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,8 @@ export function renderInstanceSelector(): void {
return;
}

const currentInstance = config.data.bundles[bundle]?.find(
(dep) => dep.serviceType === serviceType,
)?.serviceInstance;
const currentInstance = config.data.bundles[bundle]?.find((dep) => dep.serviceType === serviceType)
?.serviceInstance;

let index = 0;
for (let i = 0; i < selectBundleInstance.options.length; i++) {
Expand Down
2 changes: 1 addition & 1 deletion nodecg-io-core/extension/serviceBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export abstract class ServiceBundle<R, C> implements Service<R, C> {
this.schema = this.readSchema(pathSegments);

this.nodecg.log.info(this.serviceType + " bundle started.");
this.core = this.nodecg.extensions["nodecg-io-core"] as unknown as NodeCGIOCore | undefined;
this.core = (this.nodecg.extensions["nodecg-io-core"] as unknown) as NodeCGIOCore | undefined;
if (this.core === undefined) {
this.nodecg.log.error(
"nodecg-io-core isn't loaded! " + this.serviceType + " bundle won't function without it.",
Expand Down
2 changes: 1 addition & 1 deletion nodecg-io-core/extension/serviceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class ServiceProvider<C> {
* or undefined if the core wasn't loaded or the service type doesn't exist.
*/
export function requireService<C>(nodecg: NodeCG, serviceType: string): ServiceProvider<C> | undefined {
const core = nodecg.extensions["nodecg-io-core"] as unknown as NodeCGIOCore | undefined;
const core = (nodecg.extensions["nodecg-io-core"] as unknown) as NodeCGIOCore | undefined;
if (core === undefined) {
nodecg.log.error(
`nodecg-io-core isn't loaded! Can't require ${serviceType} service for bundle ${nodecg.bundleName}.`,
Expand Down
35 changes: 35 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions samples/artnet-console/extension/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { NodeCG } from "nodecg-types/types/server";
import { requireService } from "nodecg-io-core";
import { ArtNetServiceClient } from "nodecg-io-artnet";

module.exports = function (nodecg: NodeCG) {
nodecg.log.info("Sample bundle for Art-Net started");

const service = requireService<ArtNetServiceClient>(nodecg, "artnet");
service?.onAvailable((client) => {
// From this point on is the artnet client available
nodecg.log.info("Art-Net console has been updated, setting up interval for sending test payloads.");

// Receive DMX data
client.onDMX((dmx) => {
// dmx contains an ArtDmx object
nodecg.log.info(dmx.universe, dmx.data);
});

// Send DMX data to every channel and universe.
let value = 0;
setInterval(() => {
// send new data every 0,8 seconds.
// This is the official timing for re-transmiting data in the artnet specifciation.
if (++value > 255) value = 0;
for (let universe = 0; universe < 8; universe++) {
client.send(
universe,
// the values of the 512 channels
Array(512).fill(value),
);
}
}, 800);
});

service?.onUnavailable(() => nodecg.log.info("Art-Net console has been unset."));
};
34 changes: 34 additions & 0 deletions samples/artnet-console/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "artnet-console",
"homepage": "https://nodecg.io/RELEASE/samples/artnet",
"author": {
"name": "Tim-Tech-Dev",
"url": "https://github.com/Tim-Tech-Dev"
},
"repository": {
"type": "git",
"url": "https://github.com/codeoverflow-org/nodecg-io.git",
"directory": "samples/artnet-console"
},
"version": "0.2.0",
"private": true,
"nodecg": {
"compatibleRange": "^1.1.1",
"bundleDependencies": {
"nodecg-io-artnet": "^0.2.0"
}
},
"scripts": {
"build": "tsc -b",
"watch": "tsc -b -w",
"clean": "tsc -b --clean"
},
"license": "MIT",
"dependencies": {
"@types/node": "^15.0.2",
"nodecg-types": "^1.8.2",
"nodecg-io-core": "^0.2.0",
"nodecg-io-artnet": "^0.2.0",
"typescript": "^4.2.4"
}
}
3 changes: 3 additions & 0 deletions samples/artnet-console/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.common.json"
}