TallyArbiter
TallyArbiter copied to clipboard
[Bug]: Camera numbers swap on AtomM5 Matrix
What happened?
When assigning numbers to a M5atom Matrix by clicking the led display, the set camera number increases by 1 when the first tallys are triggered. So you have to set the camera number to 1 lower than your desired camera as a temporary workaround
Version
3.0.2
Distribution
Desktop
OS
Windows
What browsers are you seeing the problem on?
Chrome
If applicable, What Listener Clients are You Using?
M5 Stick
TallyArbiter configuration
{
"security": {
"jwt_private_key": "kE3OtAm4ASJxF5thmvz2/naTZ/sWdh0LooPOlZnteDWyyMnId+qG2a5YhqOn2gJKmxLlHXCVIeE/ztHtUHs8rtMx+jSwAFTJ5oKkZ+f3s5eg4g2sI5hGNI+Qd7W2FVpQsIiUKQ7gPDzNWHeKizKWHFwO+9xHb8I0TOagjRBELCjfFF2N1jmFH7BtdljSuFz/8rCs2h8C+p4OWTosfn+3AaemcyyRf+Sd60VaNdlbhga2sgevgYHoFGxzikJg/qt3aB9eRbA9iDkCJIbw+D+x4IJSQeFY2kwCTSg3yLmUp8B67wQBuiUZIeZ7O6RgFMlq4zQ5AnAJ01Y4wWszwWJNeQ=="
},
"users": [
{
"username": "producer",
"password": "$2b$10$s5gjVXF.Wi9OueekOocG8.7xozMWUDzdnUZV1RChlHuYigPdQrJSq",
"roles": "producer"
},
{
"username": "admin",
"password": "$2b$10$zHEDrXi8HCdSD2uyxon47.xSmVkZyqWGMCo4Ua3cYS0NGPqECMKrm",
"roles": "admin"
}
],
"cloud_destinations": [],
"cloud_keys": [],
"device_actions": [],
"device_sources": [
{
"deviceId": "b364d022",
"sourceIdx": "0",
"address": "20",
"sourceId": "630a647f",
"id": "eb27fa74"
},
{
"deviceId": "f7dab269",
"sourceIdx": "0",
"address": "21",
"sourceId": "630a647f",
"id": "91f5f12d"
},
{
"deviceId": "6c3fdd1f",
"sourceIdx": "0",
"address": "22",
"sourceId": "630a647f",
"id": "d3396ede"
}
],
"devices": [
{
"name": "Camera 01",
"enabled": true,
"id": "b364d022"
},
{
"name": "Camera 02",
"enabled": true,
"id": "f7dab269"
},
{
"name": "Camera 03",
"enabled": true,
"id": "6c3fdd1f"
}
],
"sources": [
{
"data": {
"ip": "10.20.30.101"
},
"name": "vMix",
"sourceTypeId": "58b6af42",
"reconnect": true,
"enabled": true,
"id": "630a647f",
"max_reconnects": 5,
"connected": true
}
],
"tsl_clients": [],
"tsl_clients_1secupdate": false,
"bus_options": [
{
"id": "e393251c",
"label": "Preview",
"type": "preview",
"color": "#3fe481",
"priority": 50
},
{
"id": "334e4eda",
"label": "Program",
"type": "program",
"color": "#ff002b",
"priority": 200
},
{
"id": "12c8d699",
"label": "Aux 1",
"type": "aux",
"color": "#0000FF",
"priority": 100
},
{
"id": "12c8d689",
"label": "Aux 2",
"type": "aux",
"color": "#0000FF",
"priority": 100
}
],
"externalAddress": "http://0.0.0.0:4455/#/tally",
"remoteErrorReporting": false,
"uuid": "a692e63b"
}
Relevant log output
// Code from Arduino IDE for the M5 Atom Listener:
#include <M5Atom.h>
#include <WiFi.h>
#include <WebSocketsClient.h>
#include <SocketIOclient.h>
#include <Arduino_JSON.h>
#include <PinButton.h>
#include <stdint.h>
#include <Arduino.h>
#include <WiFiManager.h>
#include <ArduinoOTA.h>
#include <ESPmDNS.h>
#include <Preferences.h>
#define DATA_PIN_LED 27
//M5 variables
PinButton btnAction(39); //the "Action" button on the device
Preferences preferences;
/* USER CONFIG VARIABLES
Change the following variables before compiling and sending the code to your device.
*/
//Tally Arbiter Server
char tallyarbiter_host[40] = "10.20.30.101";
char tallyarbiter_port[6] = "4455";
//Set staticIP to 1 if you want the client to use a static IP address. Default is DHCP.
//Note that addresses entered here will need to be confirmed when WiFi Manager runs on client.
//
//local static IP config:
#define staticIP 0
#if staticIP == 1
IPAddress stationIP = IPAddress(192, 168, 1, 195);
IPAddress stationGW = IPAddress(192, 168, 1, 1);
IPAddress stationMask = IPAddress(255, 255, 255, 0);
#endif
//Local Default Camera Number. Used for local display only - does not impact function. Zero results in a single dot displayed.
int camNumber = 0;
// Name of the device - the serial number of the listener hardware will be appended to create a unique identifier for the server.
String listenerDeviceName = "m5Atom-1";
// Enables the GPIO pinout
#define TALLY_EXTRA_OUTPUT false
/* END OF USER VARIABLES
*/
//Tally Arbiter variables
SocketIOclient socket;
WiFiManager wm; // global wm instance
JSONVar BusOptions;
JSONVar Devices;
JSONVar DeviceStates;
String DeviceId = "unassigned";
String DeviceName = "unassigned";
String ListenerType = "m5";
const unsigned long reconnectInterval = 5000;
unsigned long currentReconnectTime = 0;
bool isReconnecting = false;
#if TALLY_EXTRA_OUTPUT
const int led_program = 10;
const int led_preview = 26; //OPTIONAL Led for preview on pin G26
const int led_aux = 36; //OPTIONAL Led for aux on pin G36
#endif
String prevType = ""; // reduce display flicker by storing previous state
String actualType = "";
String actualColor = "";
int actualPriority = 0;
// default color values
int GRB_COLOR_WHITE = 0xffffff;
int GRB_COLOR_BLACK = 0x000000;
int GRB_COLOR_RED = 0xff0000;
int GRB_COLOR_ORANGE = 0xa5ff00;
int GRB_COLOR_YELLOW = 0xffff00;
int GRB_COLOR_GREEN = 0x00ff00;
int GRB_COLOR_BLUE = 0x0000ff;
int GRB_COLOR_PURPLE = 0x008080;
int numbercolor = GRB_COLOR_WHITE;
int flashcolor[] = {GRB_COLOR_WHITE, GRB_COLOR_WHITE};
int offcolor[] = {GRB_COLOR_BLACK, numbercolor};
int badcolor[] = {GRB_COLOR_BLACK, GRB_COLOR_RED};
int readycolor[] = {GRB_COLOR_BLACK, GRB_COLOR_GREEN};
int alloffcolor[] = {GRB_COLOR_BLACK, GRB_COLOR_BLACK};
int wificolor[] = {GRB_COLOR_BLACK, GRB_COLOR_BLUE};
int infocolor[] = {GRB_COLOR_BLACK, GRB_COLOR_ORANGE};
//this is the array that stores the number layout
int number[17][25] = {{
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 1,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 1,
1, 1, 1, 1, 1,
0, 1, 0, 0, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 1, 1, 0, 1,
1, 0, 1, 0, 1,
1, 0, 1, 1, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 0, 1, 0, 1,
1, 0, 1, 0, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
0, 0, 1, 0, 0,
1, 1, 1, 0, 0,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 0, 1, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 0, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 0, 1, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 1, 0, 0, 0,
1, 0, 1, 0, 0,
1, 0, 0, 1, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0
},
{ 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 0, 1,
0, 0, 0, 0, 0
},
{ 1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1
},
{ 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0
},
{ 1, 1, 1, 0, 1,
1, 0, 1, 0, 1,
1, 0, 1, 1, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1
},
{ 1, 1, 1, 1, 1,
1, 0, 1, 0, 1,
1, 0, 1, 0, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1
},
{ 1, 1, 1, 1, 1,
0, 0, 1, 0, 0,
1, 1, 1, 0, 0,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1
},
{ 1, 0, 1, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 0, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1
},
{ 1, 0, 1, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1
},
};
// this array stores all the icons for the display
int icons[13][25] = {
{ 1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1
}, // full blank
{ 0, 0, 1, 1, 1,
0, 1, 0, 0, 0,
1, 0, 0, 1, 1,
1, 0, 1, 0, 0,
1, 0, 1, 0, 1
}, // wifi 3 rings
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 1, 1,
0, 0, 1, 0, 0,
0, 0, 1, 0, 1
}, // wifi 2 rings
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 1
}, // wifi 1 ring
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
}, // reassign 1
{ 0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 1, 0, 1, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0
}, // reassign 2
{ 1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
}, // reassign 3
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
}, // setup 1
{ 0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0
}, // setup 2
{ 0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
1, 0, 0, 0, 1,
0, 0, 0, 0, 0,
0, 0, 1, 0, 0
}, // setup 3
{ 1, 0, 0, 0, 1,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 1, 0, 1, 0,
1, 0, 0, 0, 1
}, // error
{ 0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1,
0, 0, 0, 1, 0
}, // good
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
}, // no icon
};
// Logger - logs to serial number
void logger(String strLog, String strType) {
if (strType == "info") {
Serial.println(strLog);
}
else {
Serial.println(strLog);
}
}
// Set Device name
void setDeviceName() {
for (int i = 0; i < Devices.length(); i++) {
if (JSON.stringify(Devices[i]["id"]) == "\"" + DeviceId + "\"") {
String strDevice = JSON.stringify(Devices[i]["Type"]);
DeviceName = strDevice.substring(1, strDevice.length() - 1);
break;
}
}
preferences.begin("tally-arbiter", false);
preferences.putString("devicename", DeviceName);
preferences.putString("deviceid", DeviceId);
preferences.end();
logger("-------------------------------------------------", "info-quiet");
logger("DeviceName:" + String(DeviceName), "info-quiet");
logger("DeviceId:" + String(DeviceId), "info-quiet");
logger("-------------------------------------------------", "info-quiet");
}
//---------------------------------------------------------------
//HERE IS THE MAIN LED DRAWING ROUTINE aka drawNumber
void drawNumber(int arr[], int colors[]) {
for (int i = 0; i < 25; i++)
{
//Serial.println("i: " + String(i) + " color: " + String(colors[arr[i]]));
M5.dis.drawpix(i, colors[arr[i]]);
}
}
void drawMultiple(int arr[], int colors[], int param_times, int delays) {
for (int times = param_times; times > 0; times--) {
drawNumber(arr, colors);
delay(delays);
}
}
//---------------------------------------------------------------
// Determine if the device is currently in preview, program, or both
void evaluateMode() {
if (actualType != prevType) {
//M5.dis.clear();
actualColor.replace("#", "");
String hexstring = actualColor;
long colorNumber = (long) strtol( &hexstring[1], NULL, 16);
// This order is to compensate for Matrix needing grb.
int g = colorNumber >> 16;
int r = colorNumber >> 8 & 0xFF;
int b = colorNumber & 0xFF;
if (actualType != "") {
int backgroundColor = 0x10000 * r + 0x100 * g + b;
int currColor[] = {backgroundColor, numbercolor};
logger("Current color: " + String(backgroundColor), "info");
//logger("Current camNumber: " + String(camNumber), "info");
// If you want the camera number displayed during Pgm and Pvw, uncomment the following line and comment the line after.
//drawNumber(number[camNumber], currColor);
drawNumber(icons[12], currColor);
} else {
drawNumber(number[camNumber], offcolor);
}
#if TALLY_EXTRA_OUTPUT
if (actualType == "preview") {
digitalWrite(led_program, HIGH);
digitalWrite (led_preview, LOW);
digitalWrite (led_aux, LOW);
} else if (actualType == "preview") {
digitalWrite(led_program, LOW);
digitalWrite (led_preview, HIGH);
digitalWrite (led_aux, LOW);
} else if (actualType == "aux") {
digitalWrite(led_program, LOW);
digitalWrite (led_preview, LOW);
digitalWrite (led_aux, HIGH);
} else {
digitalWrite(led_program, LOW);
digitalWrite (led_preview, LOW);
digitalWrite (led_aux, LOW);
}
#endif
logger("Device is in " + actualType + " (color " + actualColor + " priority " + String(actualPriority) + ")", "info");
// This is a hack to compensate for the Matrix needing GRB.
logger(" r: " + String(g) + " g: " + String(r) + " b: " + String(b), "info");
prevType = actualType;
}
}
void startReconnect() {
if (!isReconnecting)
{
isReconnecting = true;
currentReconnectTime = millis();
}
}
void connectToServer() {
logger("---------------------------------", "info-quiet");
logger("Connecting to Tally Arbiter host: " + String(tallyarbiter_host), "info-quiet");
socket.onEvent(socket_event);
socket.begin(tallyarbiter_host, atol(tallyarbiter_port));
logger("---------------------------------", "info-quiet");
}
// Here are all the socket listen events - messages sent from Tally Arbiter to the M5
void socket_Disconnected(const char * payload, size_t length) {
logger("Disconnected from server, will try to re-connect: " + String(payload), "info-quiet");
Serial.println("disconnected, going to try to reconnect");
startReconnect();
}
void ws_emit(String event, const char *payload = NULL) {
if (payload) {
String msg = "[\"" + event + "\"," + payload + "]";
Serial.println(msg);
socket.sendEVENT(msg);
} else {
String msg = "[\"" + event + "\"]";
Serial.println(msg);
socket.sendEVENT(msg);
}
}
String strip_quot(String str) {
if (str[0] == '"') {
str.remove(0, 1);
}
if (str.endsWith("\"")) {
str.remove(str.length() - 1, 1);
}
return str;
}
void socket_event(socketIOmessageType_t type, uint8_t * payload, size_t length) {
String eventMsg = "";
String eventType = "";
String eventContent = "";
switch (type) {
case sIOtype_CONNECT:
socket_Connected((char*)payload, length);
break;
case sIOtype_DISCONNECT:
socket_Disconnected((char*)payload, length);
break;
case sIOtype_ACK:
case sIOtype_ERROR:
case sIOtype_BINARY_EVENT:
case sIOtype_BINARY_ACK:
// Not handled
break;
case sIOtype_EVENT:
eventMsg = (char*)payload;
eventType = eventMsg.substring(2, eventMsg.indexOf("\"", 2));
eventContent = eventMsg.substring(eventType.length() + 4);
eventContent.remove(eventContent.length() - 1);
logger("Got event '" + eventType + "', data: " + eventContent, "VERBOSE");
if (eventType == "bus_options") socket_BusOptions(eventContent);
if (eventType == "deviceId") socket_DeviceId(eventContent);
if (eventType == "devices") socket_Devices(eventContent);
if (eventType == "device_states") socket_DeviceStates(eventContent);
if (eventType == "flash") socket_Flash();
if (eventType == "reassign") socket_Reassign(eventContent);
break;
default:
break;
}
}
void socket_Reassign(String payload) {
logger("Socket Reassign: " + String(payload), "info-quiet");
Serial.println(payload);
String oldDeviceId = payload.substring(0, payload.indexOf(','));
String newDeviceId = payload.substring(oldDeviceId.length() + 1);
newDeviceId = newDeviceId.substring(0, newDeviceId.indexOf(','));
oldDeviceId = strip_quot(oldDeviceId);
newDeviceId = strip_quot(newDeviceId);
String reassignObj = "{\"oldDeviceId\": \"" + oldDeviceId + "\", \"newDeviceId\": \"" + newDeviceId + "\"}";
char charReassignObj[1024];
strcpy(charReassignObj, reassignObj.c_str());
ws_emit("listener_reassign_object", charReassignObj);
ws_emit("devices");
// Flash 2 times
drawNumber(icons[1], alloffcolor);
delay(200);
drawNumber(icons[4], readycolor);
delay(300);
drawNumber(icons[1], alloffcolor);
delay(200);
drawNumber(icons[5], readycolor);
delay(300);
drawNumber(icons[1], alloffcolor);
delay(200);
drawNumber(icons[6], readycolor);
delay(300);
drawNumber(icons[1], alloffcolor);
delay(200);
logger("newDeviceId: " + newDeviceId, "info-quiet");
DeviceId = newDeviceId;
preferences.begin("tally-arbiter", false);
preferences.putString("deviceid", newDeviceId);
preferences.end();
setDeviceName();
}
void socket_Flash() {
//flash the screen white 3 times
logger("The device flashed.", "info-quiet");
drawNumber(icons[1], alloffcolor);
delay(100);
drawNumber(icons[1], flashcolor);
delay(100);
drawNumber(icons[1], alloffcolor);
delay(100);
drawNumber(icons[1], flashcolor);
delay(100);
drawNumber(icons[1], alloffcolor);
delay(100);
drawNumber(icons[1], flashcolor);
delay(100);
drawNumber(icons[1], alloffcolor);
delay(100);
//then resume normal operation
evaluateMode();
}
void socket_Connected(const char * payload, size_t length) {
logger("---------------------------------", "info-quiet");
logger("Connected to Tally Arbiter host: " + String(tallyarbiter_host), "info-quiet");
isReconnecting = false;
String deviceObj = "{\"deviceId\": \"" + DeviceId + "\", \"listenerType\": \"" + listenerDeviceName.c_str() + "\", \"canBeReassigned\": true, \"canBeFlashed\": true, \"supportsChat\": false }";
logger("deviceObj = " + String(deviceObj), "info-quiet");
logger("DeviceId = " + String(DeviceId), "info-quiet");
char charDeviceObj[1024];
strcpy(charDeviceObj, deviceObj.c_str());
ws_emit("listenerclient_connect", charDeviceObj);
logger("charDeviceObj = " + String(charDeviceObj), "info-quiet");
logger("---------------------------------", "info-quiet");
}
void socket_BusOptions(String payload) {
//logger("Socket Message BusOptions: " + String(payload), "info-quiet");
BusOptions = JSON.parse(payload);
}
void socket_Devices(String payload) {
//logger("Socket Message Devices: " + String(payload), "info-quiet");
Devices = JSON.parse(payload);
setDeviceName();
}
void socket_DeviceId(String payload) {
//logger("Socket Message DeviceId: " + String(payload), "info-quiet");
DeviceId = strip_quot(String(payload));
setDeviceName();
}
void socket_DeviceStates(String payload) {
//logger("Socket Message DeviceStates: " + String(payload), "VERBOSE");
DeviceStates = JSON.parse(payload);
processTallyData();
}
String getBusTypeById(String busId) {
for (int i = 0; i < BusOptions.length(); i++) {
if (JSON.stringify(BusOptions[i]["id"]) == busId) {
return JSON.stringify(BusOptions[i]["type"]);
}
}
return "invalid";
}
String getBusColorById(String busId) {
for (int i = 0; i < BusOptions.length(); i++) {
if (JSON.stringify(BusOptions[i]["id"]) == busId) {
return JSON.stringify(BusOptions[i]["color"]);
}
}
return "invalid";
}
int getBusPriorityById(String busId) {
for (int i = 0; i < BusOptions.length(); i++) {
if (JSON.stringify(BusOptions[i]["id"]) == busId) {
return (int) JSON.stringify(BusOptions[i]["priority"]).toInt();
}
}
return 0;
}
void processTallyData() {
bool typeChanged = false;
for (int i = 0; i < DeviceStates.length(); i++) {
if (DeviceStates[i]["sources"].length() > 0) {
typeChanged = true;
actualType = getBusTypeById(JSON.stringify(DeviceStates[i]["busId"]));
actualColor = getBusColorById(JSON.stringify(DeviceStates[i]["busId"]));
actualPriority = getBusPriorityById(JSON.stringify(DeviceStates[i]["busId"]));
}
}
if (!typeChanged) {
actualType = "";
actualColor = "";
actualPriority = 0;
}
evaluateMode();
}
void connectToNetwork() {
// allow for static IP assignment instead of DHCP if stationIP is defined as something other than 0.0.0.0
#if staticIP == 1
if (stationIP != IPAddress(0, 0, 0, 0))
{
wm.setSTAStaticIPConfig(stationIP, stationGW, stationMask); // optional DNS 4th argument
}
#endif
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
logger("Connecting to SSID: " + String(WiFi.SSID()), "info");
//reset settings - wipe credentials for testing
//wm.resetSettings();
//add TA fields
WiFiManagerParameter custom_taServer("taHostIP", "Tally Arbiter Server", tallyarbiter_host, 40);
WiFiManagerParameter custom_taPort("taHostPort", "Port", tallyarbiter_port, 6);
wm.addParameter(&custom_taServer);
wm.addParameter(&custom_taPort);
wm.setSaveParamsCallback(saveParamCallback);
// custom menu via array or vector
std::vector<const char *> menu = {"wifi", "param", "info", "sep", "restart", "exit"};
wm.setMenu(menu);
// set dark theme
wm.setClass("invert");
wm.setConfigPortalTimeout(120); // auto close configportal after n seconds
bool res;
res = wm.autoConnect(listenerDeviceName.c_str());
if (!res) {
logger("Failed to connect", "error");
drawNumber(icons[10], badcolor); //display failed mark
// ESP.restart();
} else {
//if you get here you have connected to the WiFi
logger("connected...yay :)", "info");
// Flash screen if connected to wifi.
drawNumber(icons[3], wificolor); //1 ring
delay(500);
drawNumber(icons[2], wificolor); //2 rings
delay(500);
drawNumber(icons[1], wificolor); //3 rings
delay(500);
drawNumber(icons[11], readycolor); //display okay mark
delay(400);
//TODO: fix MDNS discovery
/*
int nrOfServices = MDNS.queryService("tally-arbiter", "tcp");
if (nrOfServices == 0) {
logger("No server found.", "error");
} else {
logger("Number of servers found: ", "info");
Serial.print(nrOfServices);
for (int i = 0; i < nrOfServices; i=i+1) {
Serial.println("---------------");
Serial.print("Hostname: ");
Serial.println(MDNS.hostname(i));
Serial.print("IP address: ");
Serial.println(MDNS.IP(i));
Serial.print("Port: ");
Serial.println(MDNS.port(i));
Serial.println("---------------");
}
}
*/
}
}
String getParam(String name) {
//read parameter from server, for customhmtl input
String value;
if (wm.server->hasArg(name)) {
value = wm.server->arg(name);
}
return value;
}
void saveParamCallback() {
logger("[CALLBACK] saveParamCallback fired", "info-quiet");
logger("PARAM tally Arbiter Server = " + getParam("taHostIP"), "info-quiet");
String str_taHost = getParam("taHostIP");
String str_taPort = getParam("taHostPort");
//str_taHost.toCharArray(tallyarbiter_host, 40);
//saveEEPROM();
logger("Saving new TallyArbiter host", "info-quiet");
logger(str_taHost, "info-quiet");
preferences.begin("tally-arbiter", false);
preferences.putString("taHost", str_taHost);
preferences.putString("taPort", str_taPort);
preferences.end();
}
// --------------------------------------------------------------------------------------------------------------------
// Setup is the pre-loop running program
void setup() {
Serial.begin(115200);
while (!Serial);
logger("Initializing M5-Atom.", "info-quiet");
//Save battery by turning off BlueTooth
btStop();
uint64_t chipid = ESP.getEfuseMac();
listenerDeviceName = "m5Atom-" + String((uint16_t)(chipid >> 32)) + String((uint32_t)chipid);
logger("Listener device name: " + listenerDeviceName, "info");
M5.begin(true, false, true);
delay(50);
M5.dis.drawpix(0, 0xf00000);
// blanks out the screen
drawNumber(icons[0], alloffcolor);
delay(100); //wait 100ms before moving on
//do startup animation
drawNumber(icons[7], infocolor);
delay(400);
drawNumber(icons[8], infocolor);
delay(400);
drawNumber(icons[9], infocolor);
delay(400);
connectToNetwork(); //starts Wifi connection
preferences.begin("tally-arbiter", false);
if (preferences.getString("deviceid").length() > 0) {
DeviceId = preferences.getString("deviceid");
//DeviceId = "unassigned";
}
if (preferences.getString("devicename").length() > 0) {
DeviceName = preferences.getString("devicename");
//DeviceName = "unassigned";
}
if (preferences.getString("taHost").length() > 0) {
String newHost = preferences.getString("taHost");
logger("Setting TallyArbiter host as " + newHost, "info-quiet");
newHost.toCharArray(tallyarbiter_host, 40);
}
if (preferences.getString("taPort").length() > 0) {
String newPort = preferences.getString("taPort");
logger("Setting TallyArbiter port as " + newPort, "info-quiet");
newPort.toCharArray(tallyarbiter_port, 6);
}
preferences.end();
ArduinoOTA.setHostname(listenerDeviceName.c_str());
ArduinoOTA.setPassword("tallyarbiter");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) logger("Auth Failed", "error");
else if (error == OTA_BEGIN_ERROR) logger("Begin Failed", "error");
else if (error == OTA_CONNECT_ERROR) logger("Connect Failed", "error");
else if (error == OTA_RECEIVE_ERROR) logger("Receive Failed", "error");
else if (error == OTA_END_ERROR) logger("End Failed", "error");
});
ArduinoOTA.begin();
#if TALLY_EXTRA_OUTPUT
// Enable interal led for program trigger
pinMode(led_program, OUTPUT);
digitalWrite(led_program, HIGH);
pinMode(led_preview, OUTPUT);
digitalWrite(led_preview, HIGH);
pinMode(led_aux, OUTPUT);
digitalWrite(led_aux, HIGH);
#endif
connectToServer();
delay (100);
}
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// This is the main program loop
void loop() {
socket.loop();
if (M5.Btn.wasPressed()) {
// Switch action below
if (camNumber < 17) {
drawNumber(number[camNumber], offcolor);
}
camNumber++;
if (camNumber > 16) {
camNumber = 0;
}
// Lets get some info sent out the serial connection for debugging
logger("", "info-quiet");
logger("---------------------------------", "info-quiet");
logger("Button Pressed.", "info-quiet");
logger("M5Atom IP Address: " + String(WiFi.localIP()), "info-quiet");
logger("Tally Arbiter Server: " + String(tallyarbiter_host), "info-quiet");
logger("Device ID: " + String(DeviceId), "info-quiet");
logger("Device Name: " + String(DeviceName), "info-quiet");
logger("Cam Number: " + String(camNumber), "info-quiet");
logger("---------------------------------", "info-quiet");
logger("", "info-quiet");
}
if (M5.Btn.pressedFor(5000)) {
wm.resetSettings();
ESP.restart();
}
// handle reconnecting if disconnected
if (isReconnecting)
{
unsigned long currentTime = millis();
if (currentTime - currentReconnectTime >= reconnectInterval)
{
Serial.println("trying to re-connect with server");
connectToServer();
currentReconnectTime = millis();
}
}
delay(50);
M5.update();
}
// --------------------------------------------------------------------------------------------------------------------
Error stacktrace (if applicable)
No response