Cheesy Arena Get status using remote CPU

I have been on and off on this project now for some time. Using bits of code I acquired from a group out Israel I have piece together some Auto Power Cell counters to be used with Cheesy Arena using a RaspberryPi and other bits of hardware.

Currently it Runs a Python Script to count the Power Cells and then send the appropriate keystrokes to the Cheesy Arena Alliance Scoring page. It has seem to work well but I would like to receive event and field status information as well. I have not found a way to open this communication for two way communications. This type of system integrations is outside of my current scope of knowledge.

Is there any of you that have some knowledge of how websockets work with in Cheesy Arena and can help jump start this next phase of the project.

I did need to make a few edits to the Cheesy Arena code to work around the issue of not knowing the current state of the field for instance Match Started or Ended. Having this information in the counter Processor would possibly eliminate this need. The other thing that would be good to be able to poll the system for status is to add lighting

Me and mostly another user have been looking at using OpenPLC to workaround the Rockwell implementation of the scoring system used in both the official First fields and Cheesy Arena but have met some challenges along the way.

I want to revisit the Python maybe more hacky way to try and get a positive result using hardware many of us can get.

Ultimately the question is, what status information are you trying to get, and what are you trying to send.

Some match information is sent over websockets for the audience display, and that’s sent to clients, but not backwards to the Cheesy Arena WebSockets server. You can preview that data by opening your audience display, going into your browser console, pasting this snippet, and then playing a match to see what events are sent.

ws = new WebSocket("ws://127.0.0.1:8080/displays/audience/websocket?displayId=104&background=%230f0&overlayLocation=bottom&reversed=false")

ws.onmessage = function (event) {
  console.log(event.data);
}

Emulating the scoring system is a bit more annoying, but we can peek at the linked “scoring_panel.js” when the page is loaded.

// Handles a keyboard event and sends the appropriate websocket message.
var handleKeyPress = function(event) {
  websocket.send(String.fromCharCode(event.keyCode));
};

From this we can see the browser sends string equivalents of keycodes to the server as a generic for scoring events, and if we hop over to GitHub you have the list of manual keycodes sent over and what they mean for the specific ref panel. That page already has a websocket client open that we can use, but using it elsewhere might look like this:

ws = new WebSocket("ws://127.0.0.1:8080/panels/scoring/red/websocket")
ws.send("S") //this is for the auto outer port keystroke.

The current score breakdown is also sent to all of the ref panels, and adapting the “see all events” ws.onmessage() from above would let you pick apart that data stream too for specific scoring breakdowns over time.

The above snippets are all for sending websocket data via JS, most programming languages (Python included) have some ability to send web socket data natively, making interoperability fairly easy. using GPIO and debouncing inputs would allow button-panel inputs, or potentially hooking up some generic counting hardware to get closer to a real field experience.

Hope that helps!

Match status and field status primarily.

Thanks for the detailed walk through. I’ll attempt to implement a few of these things later tonight.

As for scoring that IS exactly what we are doing. Ie sending keystrokes. The pi python code has event handlers attached to GPIO that count power cells. This count then sends that many keystrokes messages to increment the score.

If your keystroke emulator currently uses a browser, you can nix that via direct WS triggering; I don’t have your code so I didn’t want to presume and hoped the introduction was useful.

As to overall field status, the audience display and queueing display both get the “match status” of whether it’s in a match and in what status it’s in as a websocket packet titled matchTime → MatchState, where the values are integers of the enum listed here.

Field status, like how far behind you are schedule-wise, where you are in a match, as well as the upcoming schedule / match status from the audience display is redundantly available in the queuing display, where the same onmessage() snippet to poke at it works as well, though be aware that they’re sent as soon as you load the page, but custom ws listeners can ignore that event handler.

Beyond that, you may have to specifically hack at the Cheesy Arena source code to get what you want out of it. This stuff is luckily all available as-is to be used elsewhere.

1 Like

Here is my current project

I have never used the Browser Consol. I took your direction but used the socket my python has already opened:

ws = new WebSocket("ws://10.0.100.5:8080/panels/scoring/red/websocket?")

ws.onmessage = function (event) {
  console.log(event.data);
}

console output=
Looks like match state 3 and 5 would be helpfull.

{"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":0}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":1}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":2}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":3}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":4}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":5}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":6}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":7}}

VM175:2 {"type":"ping","data":null}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":8}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":9}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":10}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":11}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":12}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":13}}

VM175:2 {"type":"matchTime","data":{"MatchState":3,"MatchTimeSec":14}}

VM175:2 {"type":"matchTime","data":{"MatchState":4,"MatchTimeSec":15}}

VM175:2 {"type":"matchTime","data":{"MatchState":4,"MatchTimeSec":16}}

VM175:2 {"type":"realtimeScore","data":{"Red":{"Score":{"ExitedInitiationLine":[false,false,false],"AutoCellsBottom":[0,0],"AutoCellsOuter":[0,0],"AutoCellsInner":[0,0],"TeleopCellsBottom":[0,0,0,0],"TeleopCellsOuter":[0,0,0,0],"TeleopCellsInner":[0,0,0,0],"ControlPanelStatus":0,"EndgameStatuses":[0,0,0],"RungIsLevel":false,"Fouls":null,"ElimDq":false,"PositionControlTargetColor":0},"ScoreSummary":{"InitiationLinePoints":0,"AutoPowerCellPoints":0,"AutoPoints":0,"TeleopPowerCellPoints":0,"PowerCellPoints":0,"ControlPanelPoints":0,"EndgamePoints":0,"TotalCells":0,"FoulPoints":0,"Score":0,"StagePowerCellsRemaining":[9,15,15],"StagesActivated":[false,false,false],"ControlPanelRankingPoint":false,"EndgameRankingPoint":false},"ControlPanel":{"CurrentColor":0,"ControlPanelStatus":0,"ControlPanelLightState":0}},"Blue":{"Score":{"ExitedInitiationLine":[false,false,false],"AutoCellsBottom":[0,0],"AutoCellsOuter":[0,0],"AutoCellsInner":[0,0],"TeleopCellsBottom":[0,0,0,0],"TeleopCellsOuter":[0,0,0,0],"TeleopCellsInner":[0,0,0,0],"ControlPanelStatus":0,"EndgameStatuses":[0,0,0],"RungIsLevel":false,"Fouls":null,"ElimDq":false,"PositionControlTargetColor":0},"ScoreSummary":{"InitiationLinePoints":0,"AutoPowerCellPoints":0,"AutoPoints":0,"TeleopPowerCellPoints":0,"PowerCellPoints":0,"ControlPanelPoints":0,"EndgamePoints":0,"TotalCells":0,"FoulPoints":0,"Score":0,"StagePowerCellsRemaining":[9,15,15],"StagesActivated":[false,false,false],"ControlPanelRankingPoint":false,"EndgameRankingPoint":false},"ControlPanel":{"CurrentColor":0,"ControlPanelStatus":0,"ControlPanelLightState":0}},"MatchState":5}}

VM175:2 {"type":"matchTime","data":{"MatchState":5,"MatchTimeSec":17}}

VM175:2 {"type":"ping","data":null}

VM175:2 {"type":"matchTime","data":{"MatchState":5,"MatchTimeSec":18}}

VM175:2 {"type":"matchTime","data":{"MatchState":5,"MatchTimeSec":19}}

VM175:2 {"type":"matchTime","data":{"MatchState":5,"MatchTimeSec":20}}

VM175:2 {"type":"matchTime","data":{"MatchState":5,"MatchTimeSec":21}}

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.