Skip to content

Commit 32d10b9

Browse files
committed
initial commit for onair
0 parents  commit 32d10b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+19662
-0
lines changed

.babelrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["@babel/preset-react"]
3+
}

.github/workflows/test_build.yml

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: test_build
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
8+
9+
jobs:
10+
tests:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
node-version: [12.x]
15+
16+
steps:
17+
- uses: actions/checkout@v2
18+
19+
- name: Use Node.js ${{ matrix.node-version }}
20+
uses: actions/setup-node@v1
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
24+
- uses: actions/cache@v1
25+
id: yarn-cache
26+
with:
27+
path: node_modules
28+
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
29+
30+
- name: install dependencies
31+
if: steps.yarn-cache.outputs.cache-hit != 'true'
32+
run: yarn
33+
34+
- run: yarn build
35+
36+
- run: yarn test
37+
env:
38+
CI: true
39+
40+
build:
41+
needs: [tests]
42+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
43+
strategy:
44+
matrix:
45+
node-version: [12.x]
46+
47+
steps:
48+
49+
- uses: actions/checkout@v2
50+
51+
- name: Use Node.js ${{ matrix.node-version }}
52+
uses: actions/setup-node@v1
53+
with:
54+
node-version: ${{ matrix.node-version }}
55+
56+
- uses: actions/cache@v1
57+
id: yarn-cache
58+
with:
59+
path: node_modules
60+
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
61+
62+
- name: install dependencies
63+
if: steps.yarn-cache.outputs.cache-hit != 'true'
64+
run: yarn
65+
66+
- run: yarn build
67+
68+
- name: Generate .streamDeckPlugin
69+
run: ./tools/mac/DistributionTool -b -i ./dist/dev.cpanato.onair.sdPlugin -o ./release/
70+
71+
- name: Upload .streamDeckPlugin artifact
72+
uses: actions/[email protected]
73+
with:
74+
# Artifact name
75+
name: dev.cpanato.onair.streamDeckPlugin
76+
# Directory containing files to upload
77+
path: ./release/

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
.cache
3+
dist
4+
/.DS_Store
5+
/images/.DS_Store

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Carlos Panato
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# OnAir Stream Deck
2+
3+
# How it works?
4+
5+
It uses an external Hardware (see `hardware` directory) to notify when you are `On Air`
6+
7+
in action: https://twitter.com/comedordexis/status/1268549324092387340
8+
9+
With any StreamDeck you just install the latest release and then configure the IP address from the hardware you setup and that is it
10+
11+
12+
# How to setup the dev environment
13+
14+
1. Install all the dependencies
15+
16+
```bash
17+
yarn
18+
```
19+
20+
2. Build the project for the first time, the project uses [Parcel as bundler](https://parceljs.org/) to handle React and TypeScript
21+
22+
```bash
23+
yarn build
24+
```
25+
26+
3. Package the plugin
27+
28+
```bash
29+
./tools/mac/DistributionTool -b -i ./dist/dev.cpanato.onair.sdPlugin -o ./release/
30+
```
31+
32+
# References
33+
34+
- [Steam Deck SDK docs](https://developer.elgato.com/documentation/)
35+
36+
# Contributing
37+
38+
Feel free to send in any pull requests.

hardware/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Hardware
2+
3+
To build the Hardware you can follow
4+
5+
https://learn.adafruit.com/3d-printed-iot-on-air-sign-for-twitch?view=all
6+
7+
The source code for the hardware is in the `onAir` directory.
8+

hardware/onAir/arduino_secrets.h

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID "WIFI_NAME"
2+
#define SECRET_PASS "WIFI_PASSWORD"

hardware/onAir/onAir.ino

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
WiFi Web Server
3+
4+
A simple web server that shows the value of the analog input pins.
5+
using a WiFi shield.
6+
7+
This example is written for a network using WPA encryption. For
8+
WEP or WPA, change the WiFi.begin() call accordingly.
9+
10+
Circuit:
11+
* WiFi shield attached
12+
* Analog inputs attached to pins A0 through A5 (optional)
13+
14+
*/
15+
16+
#include <SPI.h>
17+
#include <WiFi101.h>
18+
#include <FastLED.h>
19+
20+
21+
#include "arduino_secrets.h"
22+
// Please enter your sensitive data in the Secret arduino_secrets.h
23+
char ssid[] = SECRET_SSID; // your network SSID (name)
24+
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
25+
int keyIndex = 0; // your network key Index number (needed only for WEP)
26+
27+
int onAir = 0;
28+
29+
// How many leds in your strip?
30+
#define NUM_LEDS 15
31+
#define DATA_PIN 12
32+
33+
// Define the array of leds
34+
CRGB leds[NUM_LEDS];
35+
36+
int status = WL_IDLE_STATUS;
37+
38+
WiFiServer server(80);
39+
40+
void setup() {
41+
WiFi.setPins(8,7,4,2);
42+
43+
FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
44+
//Initialize serial and wait for port to open:
45+
// Serial.begin(9600);
46+
// while (!Serial) {
47+
// ; // wait for serial port to connect. Needed for native USB port only
48+
// }
49+
colorWipe(0x0000FF, 50);
50+
51+
// check for the presence of the shield:
52+
if (WiFi.status() == WL_NO_SHIELD) {
53+
Serial.println("WiFi shield not present");
54+
// don't continue:
55+
while (true);
56+
}
57+
58+
// attempt to connect to WiFi network:
59+
while (status != WL_CONNECTED) {
60+
Serial.print("Attempting to connect to SSID: ");
61+
Serial.println(ssid);
62+
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
63+
status = WiFi.begin(ssid, pass);
64+
65+
// wait 10 seconds for connection:
66+
delay(10000);
67+
}
68+
server.begin();
69+
// you're connected now, so print out the status:
70+
// printWiFiStatus();
71+
colorWipe(0x000000, 50);
72+
}
73+
74+
75+
void loop() {
76+
// listen for incoming clients
77+
WiFiClient client = server.available();
78+
if (client) {
79+
// an http request ends with a blank line
80+
boolean currentLineIsBlank = true;
81+
while (client.connected()) {
82+
if (client.available()) {
83+
char c = client.read();
84+
85+
// if you've gotten to the end of the line (received a newline
86+
// character) and the line is blank, the http request has ended,
87+
// so you can send a reply
88+
if (c == '\n' && currentLineIsBlank) {
89+
// send a standard http response header
90+
client.println("HTTP/1.1 200 OK");
91+
client.println("Content-Type: text/html");
92+
client.println("Connection: close"); // the connection will be closed after completion of the response
93+
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
94+
client.println();
95+
96+
if (onAir == 0) {
97+
client.println("{\"status\": \"on\"}");
98+
colorWipe(0x008000, 50);
99+
onAir = 1;
100+
} else if (onAir == 1) {
101+
client.println("{\"status\": \"off\"}");
102+
colorWipe(0x000000, 50);
103+
onAir = 0;
104+
}
105+
break;
106+
}
107+
if (c == '\n') {
108+
// you're starting a new line
109+
currentLineIsBlank = true;
110+
}
111+
else if (c != '\r') {
112+
// you've gotten a character on the current line
113+
currentLineIsBlank = false;
114+
}
115+
}
116+
}
117+
// give the web browser time to receive the data
118+
delay(1);
119+
120+
// close the connection:
121+
client.stop();
122+
}
123+
}
124+
125+
void colorWipe(uint32_t c, uint8_t wait) {
126+
for(uint16_t i=0; i<NUM_LEDS; i++) {
127+
leds[i] = c;
128+
}
129+
FastLED.show();
130+
delay(wait);
131+
}
132+
133+
134+
void printWiFiStatus() {
135+
// print the SSID of the network you're attached to:
136+
Serial.print("SSID: ");
137+
Serial.println(WiFi.SSID());
138+
139+
// print your WiFi shield's IP address:
140+
IPAddress ip = WiFi.localIP();
141+
Serial.print("IP Address: ");
142+
Serial.println(ip);
143+
144+
// print the received signal strength:
145+
long rssi = WiFi.RSSI();
146+
Serial.print("signal strength (RSSI):");
147+
Serial.print(rssi);
148+
Serial.println(" dBm");
149+
}

images/categoryIcon.png

69.3 KB
Loading

images/[email protected]

69.3 KB
Loading

images/onair/.DS_Store

6 KB
Binary file not shown.

images/onair/actionDefaultImage.png

68.6 KB
Loading

images/onair/[email protected]

68.6 KB
Loading

images/onair/actionFailImage.png

69.3 KB
Loading

images/onair/[email protected]

68.6 KB
Loading

images/onair/actionIcon.png

68.6 KB
Loading

images/onair/[email protected]

68.6 KB
Loading

images/onair/actionSuccessImage.png

68.6 KB
Loading

images/onair/[email protected]

69.3 KB
Loading

images/pluginIcon.png

69.3 KB
Loading

images/[email protected]

69.3 KB
Loading

jest.config.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
preset: "ts-jest",
3+
testEnvironment: "jsdom"
4+
};

manifest.json

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"Actions": [
3+
{
4+
"Icon": "images/onair/actionIcon",
5+
"Name": "OnAir Status",
6+
"States": [
7+
{
8+
"Image": "images/onair/actionSuccessImage",
9+
"TitleAlignment": "bottom",
10+
"FontSize": "11"
11+
},
12+
{
13+
"Image": "images/onair/actionFailImage",
14+
"TitleAlignment": "bottom",
15+
"FontSize": "11"
16+
},
17+
{
18+
"Image": "images/onair/actionDefaultImage",
19+
"TitleAlignment": "bottom",
20+
"FontSize": "11"
21+
}
22+
],
23+
"SupportedInMultiActions": false,
24+
"Tooltip": "Show your On Air status",
25+
"UUID": "dev.cpanato.onair"
26+
}
27+
],
28+
"SDKVersion": 2,
29+
"Author": "cpanato",
30+
"PropertyInspectorPath": "pi/index.html",
31+
"Category": "OnAir Status for Stream Deck",
32+
"CategoryIcon": "images/categoryIcon",
33+
"CodePath": "plugin/index.html",
34+
"Description": "Show your On Air status.",
35+
"Name": "On Air for StreamDeck",
36+
"Icon": "images/pluginIcon",
37+
"URL": "https://cpanato.dev",
38+
"Version": "1.0.0",
39+
"OS": [
40+
{
41+
"Platform": "mac",
42+
"MinimumVersion": "10.11"
43+
},
44+
{
45+
"Platform": "windows",
46+
"MinimumVersion": "10"
47+
}
48+
],
49+
"Software": {
50+
"MinimumVersion": "4.1"
51+
}
52+
}

0 commit comments

Comments
 (0)