Skip to content

Commit

Permalink
Add support for setting the channel bandwidth.
Browse files Browse the repository at this point in the history
  • Loading branch information
patfair committed Jun 4, 2024
1 parent e247d1f commit 2948e40
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The `/status` GET endpoint returns the current status of the access point. It re
$ curl http://10.0.100.2:8081/status
{
"channel": 93,
"channelBandwidth": "HT40",
"status": "ACTIVE",
"stationStatuses": {
"blue1": null,
Expand Down Expand Up @@ -92,6 +93,7 @@ The `/configuration` POST endpoint allows the access point to be configured. It
```
$ curl http://10.0.100.2:8081/configuration -XPOST -d '{
"channel": 93,
"channelBandwidth": "HT20",
"stationConfigurations": {
"red1": {"ssid": "1111", "wpaKey": "11111111"},
"blue2": {"ssid": "5555", "wpaKey": "55555555"}
Expand All @@ -105,6 +107,7 @@ The `/status` endpoint can then be polled to check whether the configuration has
$ curl http://10.0.100.2:8081/status
{
"channel": 93,
"channelBandwidth": "HT20",
"status": "CONFIGURING",
"stationStatuses": {
"blue1": null,
Expand Down
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"github.com/patfair/frc-radio-api/radio"
"github.com/patfair/frc-radio-api/web"
"log"
Expand All @@ -22,9 +23,11 @@ func main() {
setupLogging()

radio := radio.NewRadio()
fmt.Println("created radio")

// Launch the web server in a separate thread.
webServer := web.NewWebServer(radio)
fmt.Println("created webserver")
go webServer.Run()

// Run the radio event loop in the main thread.
Expand All @@ -50,5 +53,4 @@ func setupLogging() {
log.Printf("error opening log file; logging to stdout instead: %v", err)
}
log.Println("Starting FRC Radio API...")

}
16 changes: 15 additions & 1 deletion radio/configuration_request_ap.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ type ConfigurationRequest struct {
// 5GHz or 6GHz channel number for the radio to use. Set to 0 to leave unchanged.
Channel int `json:"channel"`

// Channel bandwidth mode for the radio to use. Valid values are "HT20" and "HT40". Set to an empty string to leave
// unchanged.
ChannelBandwidth string `json:"channelBandwidth"`

// SSID and WPA key for each team station, keyed by alliance and number (e.g. "red1", "blue3). If a station is not
// included, its network will be disabled by setting its SSID to a placeholder.
StationConfigurations map[string]StationConfiguration `json:"stationConfigurations"`
Expand All @@ -31,7 +35,7 @@ var validLinksysChannels = []int{36, 40, 44, 48, 149, 153, 157, 161, 165}

// Validate checks that all parameters within the configuration request have valid values.
func (request ConfigurationRequest) Validate(radio *Radio) error {
if request.Channel == 0 && len(request.StationConfigurations) == 0 {
if request.Channel == 0 && request.ChannelBandwidth == "" && len(request.StationConfigurations) == 0 {
return errors.New("empty configuration request")
}

Expand All @@ -54,6 +58,16 @@ func (request ConfigurationRequest) Validate(radio *Radio) error {
}
}

if request.ChannelBandwidth != "" {
// Validate channel bandwidth.
if radio.Type == TypeLinksys {
return fmt.Errorf("channel bandwidth cannot be changed on %s", radio.Type.String())
}
if request.ChannelBandwidth != "HT20" && request.ChannelBandwidth != "HT40" {
return fmt.Errorf("invalid channel bandwidth: %s", request.ChannelBandwidth)
}
}

// Validate station configurations.
for stationName, stationConfiguration := range request.StationConfigurations {
stationNameValid := false
Expand Down
10 changes: 10 additions & 0 deletions radio/configuration_request_ap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ func TestConfigurationRequest_Validate(t *testing.T) {
err = request.Validate(vividHostingRadio)
assert.EqualError(t, err, "invalid channel for TypeVividHosting: 36")

// Invalid channel bandwidth.
request = ConfigurationRequest{ChannelBandwidth: "HT30"}
err = request.Validate(vividHostingRadio)
assert.EqualError(t, err, "invalid channel bandwidth: HT30")

// Channel bandwidth not supported on Linksys.
request = ConfigurationRequest{ChannelBandwidth: "HT20"}
err = request.Validate(linksysRadio)
assert.EqualError(t, err, "channel bandwidth cannot be changed on TypeLinksys")

// Invalid station.
request = ConfigurationRequest{
StationConfigurations: map[string]StationConfiguration{"red4": {Ssid: "254", WpaKey: "12345678"}},
Expand Down
8 changes: 8 additions & 0 deletions radio/radio_ap.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ type Radio struct {
// 5GHz or 6GHz channel number the radio is broadcasting on.
Channel int `json:"channel"`

// Channel bandwidth mode for the radio to use. Valid values are "HT20" and "HT40".
ChannelBandwidth string `json:"channelWidth"`

// Enum representing the current configuration stage of the radio.
Status radioStatus `json:"status"`

Expand Down Expand Up @@ -109,6 +112,7 @@ func (radio *Radio) isStarted() bool {
func (radio *Radio) setInitialState() {
channel, _ := uciTree.GetLast("wireless", radio.device, "channel")
radio.Channel, _ = strconv.Atoi(channel)
radio.ChannelBandwidth, _ = uciTree.GetLast("wireless", radio.device, "htmode")
_ = radio.updateStationStatuses()
}

Expand All @@ -118,6 +122,10 @@ func (radio *Radio) configure(request ConfigurationRequest) error {
uciTree.SetType("wireless", radio.device, "channel", uci.TypeOption, strconv.Itoa(request.Channel))
radio.Channel = request.Channel
}
if request.ChannelBandwidth != "" {
uciTree.SetType("wireless", radio.device, "htmode", uci.TypeOption, request.ChannelBandwidth)
radio.ChannelBandwidth = request.ChannelBandwidth
}

if radio.Type == TypeLinksys {
// Clear the state of the radio before loading teams; the Linksys AP is crash-prone otherwise.
Expand Down
3 changes: 3 additions & 0 deletions web/configuration_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

func TestWeb_configurationHandler(t *testing.T) {
ap := radio.NewRadio()
ap.Type = radio.TypeVividHosting
web := NewWebServer(ap)

// Empty request should result in an error.
Expand Down Expand Up @@ -40,6 +41,7 @@ func TestWeb_configurationHandler(t *testing.T) {
`
{
"channel": 149,
"channelBandwidth": "HT20",
"stationConfigurations": {
"red1": {"ssid": "9991", "wpaKey": "11111111"},
"red2": {"ssid": "9992", "wpaKey": "22222222"},
Expand All @@ -56,6 +58,7 @@ func TestWeb_configurationHandler(t *testing.T) {
if assert.Equal(t, 1, len(ap.ConfigurationRequestChannel)) {
request := <-ap.ConfigurationRequestChannel
assert.Equal(t, 149, request.Channel)
assert.Equal(t, "HT20", request.ChannelBandwidth)
assert.Equal(t, 6, len(request.StationConfigurations))
assert.Equal(
t, radio.StationConfiguration{Ssid: "9991", WpaKey: "11111111"}, request.StationConfigurations["red1"],
Expand Down

0 comments on commit 2948e40

Please sign in to comment.