rlgs:en:ag1

Agents

Diese Seite ist auf deutsch verfügbar.

Agents are the gadgets on the field which players can hear, see and touch. Inside the agent is a small computer1) running an operating software2). An agent has different purposes and is designed to meet this task. Some agents are build to be a capture point. They must not break, just because they took some lines of paint or BBs. Some agents are kept in the spawn area. They have a display and maybe some sound output to inform the teams about the game situations. Sometimes we need only a siren somewhere on the field which nobody interacts with directly.

The output devices are

  • 5x colored lights in the following order: white, red, yellow, green, blue. The lights are usually 12 Volt LED strips.
  • 4x sirens with different signals. These sirens are connected via a relay. Depending on the relay's trigger level (high or low) you will have to apply a pull up oder pull down resistor. In future versions of the PCB these resistors will be provided on the board.
  • 1x 12 Volt buzzer for close range notifications.
  • 1x LCD with 20 cols x 4 rows
  • 1 pushbutton for player interaction. In fact there is also a second button on the breakout board, but we don't use it, yet.

All those devices are optional. An agent doesn't have to support all of them. In fact we haven't yet build any agent, that had a full device set. A complete system, should not be necessary. However, the software understands all signals, even if the addressed devices are not connected. In this case the signal is accepted but ignored.

Agents do not know anything about why they are flashing LEDs, sounding sirens or why somebody presses their buttons. They completely rely on the commander to tell them what to do. The commander is the only one who keeps track about the game situation.

Hardware

The agent software is supposed to be run on a Raspberry Pi computer when used on the playing field. See Software section below.

There is a breakout board to easily connect a Raspberry Pi computer to the external hardware. You can get Your own PCB from any pcb manufacturing service, that accepts a ( Gerber file). Of course You can directly order the PCB from JLCPCB, like we did. Ein sog. Breakout Board, dass Ihr euch direkt bei einem beliebigen Platinen Dienst fertigen lassen könnt oder direkt bei JLCPCB.

  • 6x LEDs colored: white (2x), red, yellow, green, blue. the longer pin of the led inserted on the upper side.
  • 6x IRLZ34 N-Channel MOSFET the metal cooler is facing to the upper side
  • 6x 220 Ω resistors
  • 5x 1 kΩ resistors
  • 8x 10 kΩ resistors
  • (optional) WAGO connectors 10pin and 8pin - see list of materials above. When used, the connectors are facing to the outside - away from the PCB.
  • 2x 6x6mm microbuttons. The metal contacts are on the left and right side.

Block Pin Belegung/Usage
U11Button 1
2Signal Line for Relay 3 → Siren 3
3Signal Line for Relay 2 → Siren 2
4Signal Line for Relay 1 → Siren 1
5GND Return-Line for 12 Volts Buzzer
6GND Return-Line for 12 Volts, LED blue
7GND Return-Line for 12 Volts, LED green
8GND Return-Line for 12 Volts, LED yellow
9GND Return-Line for 12 Volts, LED red
10GND Return-Line for 12 Volts, LED white
H1allGround
H615 Volt
2I2C Data SDA
3I2C Clock SCL
4Ground
P115 Volts
23,3 Volts
3Ground
4Ground
5Neopixel unused
6Button 2 unused
7I2C Clock SCL
8I2C Data SDA

The LEDs on the pcb are control lights for the stripes that are attached later.

LED Stripes always have 2 wires connected (12 Volt and ground). We connect the 12V line directly to the PLUS of the battery. The ground lines are connected to the corresponding pin at the U1 block, Pin #6 - #9.

The connection of the buzzer is the same as with the LEDs. Connect the 12V line directly to the PLUS of the battery. The ground return-line goes to pin 5 at U1 block.

Software

The Software realizes when it is run on a normal desktop computer. In this case, the hardware is simulated in a window. This is very helpful to try out new game modes during development. It may also be handy for You to get a feeling for the whole system.

There is a RLGS simulator, which is a prepared virtual machine with everything set up and pre installed properly.

Agents are supposed to run on Raspberry Pi computers with several input and output devices connected to them. Like LED stripes, sirens (switched by relay boards), push buttons, LCDs etc. But it is also possible to run them on a standard desktop computers (Mac, Windows, Linux). In this case, they start up a Swing GUI to simulate the aforementioned devices on the screen or via the sound card.

We use the Pi4J framework to connect the hardware to our Java source code. The whole framework is about to change drastically with the version 2. But for now we stick to Version 1, which still relies on the now deprecated WiringPi project, as it runs very well. Please note, that the Pin numbering used in the config files are named according to the WiringPi scheme.

WiringPi is not available in Raspbian anymore or as sourcecode. Until we are moving on to pi4j 2.0 (which based on pigpio), we stick with a source code mirror for WiringPi on GitHub, which works for us.

not yet…

The agent is written in Java and therefor available on nearly any platform. There are ready-made packages for Windows, Mac, Linux and Raspbian. The Raspbian version is only available as a service or demonized version. Linux versions are distributed via a package repository at flashheart.de. Refer to the download page for more information.

The agent creates a workspace folder (if missing). The folder's location has to be specified via a -D argument on the java command line.

java -Dworkspace=/home/pi/rlgagent -jar /opt/rlgagent/rlgagent.jar

The standard installation packages contain this setting in the rlgagent.vmoptions file located in the installation folder.

  • PC Linux as desktop application: /opt/rlgagent
  • Raspian or Linux as a service/demon: /opt/rlagentd
  • Mac: /Applications/rlgagent
  • Windows: %PROGRAMFILES%\rlgagent

The workspace folder contains

  • the config.txt file - see Configs
  • a folder for log files. The agent archives a log file from a previous day on startup. The current day's or most recent file is always named rlgagent.log
  • the mqtt persistence directory (technical stuff - ignore it)
  • (optional) an audio folder for voices and intro songs

The structure looks like this:

rlgagent
|--rlgagent-385d8f4a-a0b7-496a-b3ca-7fe0f1cf20a0-tcplocalhost1883
| |--.lck
|--config.txt
|--audio
| |--announce
| | |--overtime.mp3
| | |--welcome.mp3
| | |--firstblood.mp3
| |--intro
| | |--future1.mp3
| | |--insomnia.mp3
| | |--feuerfrei.mp3
| | |--future2.mp3
| | |--bf3.mp3
| | |--eminem.mp3
| | |--sirius.mp3
| | |--metallica.mp3
| | |--nodyahead.mp3
| | |--thunder.mp3
| | |--killbill.mp3
|--logs
| |--rlgagent.log
| |--2022-06-21.rlgagent.log.gz
| |--2022-06-29.rlgagent.log.gz
| |--2022-06-27.rlgagent.log.gz
| |--2022-07-01.rlgagent.log.gz

This is a standard Java properties file. If missing, it will be created with default values.

# Settings rlgagent
# the Raspi GPIO pin for the corresponding devices (Wiring Pi numbering scheme). Default sets the assignment
# to the standard agent [[https://easyeda.com/tloehr/rlg-mainboard-v11_copy|PCB]].
btn01=GPIO 3
btn02=GPIO 4
buzzer=GPIO 26
led_blu=GPIO 22
led_grn=GPIO 21
led_red=GPIO 1
led_wht=GPIO 2
led_ylw=GPIO 5
sir1=GPIO 7
sir2=GPIO 0
sir3=GPIO 6
sir4=GPIO 23
# Sets the debounce delay interval (in milliseconds) for all pin states.
# prevents //nervous buttons// from sending too many signals. increase if necessary.
button_debounce=200
# dimensions for the LCD.
lcd_cols=20
lcd_rows=4
# address on the i2c bus for the connected LCD
lcd_i2c_address=0x27
# the verbosity of the log file. possible values: OFF, DEBUG, TRACE, INFO, ERROR, WARN
loglevel=TRACE
# if a MCP23017 port extender is used, this is the address to find it on the i2c bus
mcp23017_i2c_address=0x20
# the [[http://mpg321.sourceforge.net/|mpg321] has to be installed on the agent, if we want
# to play sound files (useful for countdown voices or announcements). this is the path to the executable
mpg321_bin=/usr/local/bin/mpg321
# if options are needed (especially on the raspi) there can be added here
mpg321_options=
# the ordered list of mqtt brokers to search for. The agent tries to connect to the entries in this list
# - one by one. If the connection breaks during the game, the agent keeps trying to reconnect again.
mqtt_broker=mqtt mqtta mqttb
# settings for paho client
# https://www.eclipse.org/paho/files/javadoc/org/eclipse/paho/client/mqttv3/MqttConnectOptions.html#setCleanSession-boolean-
mqtt_clean_session=true
# the maximum number of messages in transit and not yet delivered.
mqtt_max_inflight=1000
# port address for the broker
mqtt_port=1883
# to be used for the event messages sent by this agent from 0 to 2. Where 0 is at most once, 1 at least once, 2 exactly once.
# https://en.wikipedia.org/wiki/MQTT#Quality_of_service|quality of service
mqtt_qos=2
# settings for paho client
# https://www.eclipse.org/paho/files/javadoc/org/eclipse/paho/client/mqttv3/MqttConnectOptions.html#setAutomaticReconnect-boolean-
mqtt_reconnect=true
# sets whether the event messages from this agent should be
# https://www.hivemq.com/blog/mqtt-essentials-part-8-retained-messages/
mqtt_retained=true
# the root element of the message topics to subscribe and send to. Keep the defaults.
mqtt_root=rlg
# settings for paho client
# https://www.eclipse.org/paho/files/javadoc/org/eclipse/paho/client/mqttv3/MqttConnectOptions.html#setConnectionTimeout-int-
mqtt_timeout=10
# the mqtt name of the agent by which it will be adressed within the network
# not to be confused with the DNS name. doens't have to be the same.
myid=ag01
# set if the attached siren relais trigger on low or high
trigger_on_high_sir1=true
trigger_on_high_sir2=true
trigger_on_high_sir3=true
trigger_on_high_sir4=true
# a random but unique id which is used to connect to the broker.
uuid=7823554b-b4b1-481d-ba2c-4f73f888efb
# only for Raspberry Pis. command line to be execute every 5 seconds. The results are parsed and sent to the commander via a status event message.
wifi_cmd=iwconfig wlan1

Messaging

The commander and the agents communicate via a MQTT broker.

Every agent has it's own channels:

  • inbound command channel: /<mqtt_root>/cmd/<myid>/# agent listens to what the commander wants him to do
  • outbound event channel: /<mqtt_root>/evt/<myid>/# agent sends notifications about events that happened to him (e.G. button presses)

Every command has a subchannel on the inbound channel. E.G. signals to ag01 are sent to /rlg/cmd/ag01/signals, LCD content to /rlg/cmd/ag01/paged etc. The examples below are written with these default settings in mind.

Topic: /rlg/cmd/<myid>/paged

Agents can handle LCDs driven by the Hitachi HD44780 controller chip. LCDs with line/col should have a text screen dimension of 20×4. As You can see in the JavaDoc for MyLCD, the display output is organized in pages, which cycle continously. Refer to the MyLCD class for more details.

Every screen page is identified by a string handle. Please note that there is always an anchor page called page0, which cannot be removed.

Setting the page content

The following payload will set the content of 2 pages. A new page will be created automatically when needed. It is also automatically removed, when this new page is missing from a later page content command.

{
  "page1": [
    "   >>> BLUE  <<<   ",
    "${blue_l1}",
    "${blue_l2}",
    "Red->${red_tickets}:${blue_tickets}<-Blue"
  ],
  "page0": [
    "   >>> RED   <<<   ",
    "${red_l1}",
    "${red_l2}",
    "Red->${red_tickets}:${blue_tickets}<-Blue"
  ]
}

Content exceeding the supported display dimension (e.g. 20×4) will be truncated.

As You can see, we used template expressions in the last example like ${blue_l1}. These expressions refer to a variable (see the next section) and will be replaced by the bound variable content. The variable content is updated every time the page is displayed.

There are also timer variables, which are always counted down to zero. So You can display a running timer, even when there is only one page to be displayed. (see timers)

Topic: /rlg/cmd/<myid>/vars

Template expressions are replaced on the LCD screen with their corresponding values. There are different ways how a variable can be set.

Preset variables

These variables are set by the agent itself. They contain useful system values and should not be overwritten by a user.

  • wifi → the current Wi-Fi signal strength
  • ssid → ssid of the Wi-Fi connected to.
  • agversion → current software version of the agent
  • agbuild → current software build of the agent
  • agbdate → current software build-date of the agent

Dynamic variables

The commander can set any variable to a specific value to fill out the page templates on the display, as described above. Example message as generated by the conquest class to broadcast the current score.

{
  "red_l2": "",
  "blue_tickets": "250",
  "blue_l1": "",
  "red_l1": "",
  "blue_l2": "",
  "red_tickets": "250"
}

Timers

Topic: /rlg/cmd/<myid>/timers

Timers are also variables, but they have to be Long values. The agent interprets those values as remaining time in seconds, counting them down after reception. The timer template is replaced by the time in the format hh:ss and disappears when the time reaches zero.

{
  "remaining": 61
}

The above message will start a timer at 1 minute 1 second. A display line:

{
  "timer": "${remaining}"
}

will show up on the LCD as timer: 01:01 - and counting

The signal scheme progress also reacts according to a timer - calculating a percentage between start value and zero to display a progress.

{
  "_clearall": "0"
}

Removes all timers.

Topic: /rlg/cmd/<myid>/signals

Signals are sent out by the agent optically (LEDs) or accoustically (Sirens, Buzzer).

Signal schemes are lists of pairs with on and off durations (in milliseconds). Every list is preceded by the number of repeats. If a scheme should go on forever (until overwritten by a new command), the repeat_count can be replaced by the infty keyword (in fact, there is no infinity, it is Long.MAX_VALUE*, but for our purpose this would take forever). A repeat_count of 0, turns off the signal. Like so: 0: or the word off (which is also understood).

The syntax of the scheme is:

<repeat_count>:[on|off],<period_in_ms>;[on|off],<period_in_ms>

Devices (like LEDs or sirens) connected to these pins via a MOSFET transistors or Relays are switched on and off accordingly.

Preset signal schemes

By default, an agent recognizes some standard schemes which are translated locally. In fact, the commander makes extensive use of these “macros”, as they cover most of its needs.

  • Singles
    • very_long1:on,5000;off,1
    • long1:on,2500;off,1
    • medium1:on,1000;off,1
    • short1:on,500;off,1
    • very_short1:on,250;off,1
  • Recurring
    • very_slowinfty:on,1000;off,5000
    • slowinfty:on,1000;off,2000
    • normalinfty:on,1000;off,1000
    • fastinfty:on,500;off,500
    • very_fastinfty:on,250;off,250
    • netstatusinfty:on,250;off,750
  • Buzzer signals
    • single_buzz1:on,75;off,75
    • double_buzz2:on,75;off,75
    • triple_buzz3:on,75;off,75

Hence, a signal with a payload like {"led_red":"slow"} would translate to {"led_red":"infty:on,1000;off,2000"}.

Dynamic signal schemes

In contrast to static schemes, the agents can also handle dynamic signalling. We can show hours and minutes or a progressing timer running from 0% to 100%.

<figure>

some caption

</figure> The above example shows two agents signalling the same remaining timer. The short remaining time is displayed as a progress bar, the long remaining time is signalled to show the remaining seconds.

Progress

{
  "led_all":"progress:remaining"
}

This message will bind all leds to the “remaining” timer, showing a progressing situation. When the timer has run out, the leds are switched off.

Timer

{
  "led_grn":"timer:remaining"
}

This message will bind the green led to the “remaining” timer. When the timer has run out, the led is switched off. The time will be signalled by a special blink code.

time of led set to onstands for
1 second1 hour
625 milliseconds10 minutes
250 milliseconds1 minute

Smaller time units can not be signalled.

The agent abstracts devices from their GPIO counterparts on the Raspi. The following devices are recognized: led_wht, led_red, led_ylw, led_grn, led_blu, sir1, sir2, sir3, btn01, btn02, buzzer. “sir” stands for siren. So the meaning of this list should be pretty obvious.

There are 3 device groups:

  • all → All pins.
  • led_allled_wht, led_red, led_ylw, led_grn, led_blu
  • sir_allsir1, sir2, sir3

Example:

A signal which causes the agent to buzz two times (75 ms) would have a payload like this:

{"buzzer":"2:on,75;off,75"}

If we want all LEDs to blink every second (until further notice), we would send this:

{"led_all":"infty:on,1000;off,1000"}

or in short:

{"led_all":"normal"}

We can combine multiple payloads into one message. Also for the other commands, not only signals.

{
  "led_all": "infty:on,250;off,2500",
  "sir1": "long"
}

Topic: /rlg/cmd/<myid>/play

{
  "subpath": "intro",
  "soundfile": "bf3"
}

The subpath is located under the audio folder (see Workspace). The mp3 extension is added to the soundfile. If a soundfile is missing or the player is not installed, this command will be ignored.

Events are something that happens to or on the agent. They are reported to the commander.

Topic: /rlg/evt/ag01/btn01 or /rlg/evt/ag01/btn02

The use of a button is divided into two separate events:

  1. The first one reporting that the button is pressed down: {"button":"down"}
  2. the second one when the button is released again: {"button":"up"}

Topic: /rlg/evt/ag01/status

Every 60 seconds an agent reports its current status to the commander. Very important to tell, whether all agents are working correctly during a match.

{
  "mqtt-broker": "localhost",
  "netmonitor_cycle": 96,
  "wifi": "PERFECT",
  "mqtt_connect_tries": 1,
  "essid": "!DESKTOP!",
  "last_ping": "16.03.22, 15:06:27",
  "link": "--",
  "freq": "--",
  "ping_max": "0.044",
  "bitrate": "--",
  "version": "1.0.1.387",
  "ap": "!DESKTOP!",
  "txpower": "--",
  "ping_success": "ok",
  "powermgt": "--",
  "ping_loss": "0%",
  "ping_min": "0.044",
  "ping_avg": "0.044",
  "signal": "-30",
  "ping_host": "localhost",
  "timestamp": "2022-03-16T15:06:27.107081+01:00[Europe/Berlin]"
}


1)
Raspberry Pi
2)
written in Java, so it can also be used on a common desktop computer
  • rlgs/en/ag1.txt
  • Last modified: 2022/07/06 14:13
  • by flashheart