Skip to content

Commit

Permalink
Merge pull request #80 from nitram509/feature/gs316-port-set
Browse files Browse the repository at this point in the history
make GS316 feature complete
  • Loading branch information
nitram509 authored Dec 29, 2024
2 parents e3a6f92 + b35da3b commit 6d202d5
Show file tree
Hide file tree
Showing 24 changed files with 1,025 additions and 528 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@

# ntgrrc (Netgear Remote Control) CHANGELOG

## v0.12.0

* Add support to show and change POE settings
* Add show port status, when requesting port settings

----

## v0.11.0

* Add support poe reset (cycle power) for gs316xx (#70); many thanks to @electron1963 for testing and supporting this feature
Expand Down
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@ are very welcome**.

A green tick means it was successfully tested.

| Firmware | GS305EP(P) | GS308EP | GS308EPP | GS316EP(P) |
|-----------|------------|----------|----------|--------------|
| V1.0.0.8 || (likely) || - |
| v1.0.0.10 || (likely) || - |
| V1.0.1.1 | (likely) || (likely) | - |
| V1.0.3.4 | - | - | - | experimental |
| V1.0.3.7 | - | - | - | experimental |
| V1.0.4.4 | - | - | - | experimental |
| Firmware | GS305EP(P) | GS308EP | GS308EPP | GS316EP(P) |
|-----------|------------|----------|----------|------------|
| V1.0.0.8 || (likely) || - |
| v1.0.0.10 || (likely) || - |
| V1.0.1.1 | (likely) || (likely) | - |
| V1.0.3.4 | - | - | - | |
| V1.0.3.7 | - | - | - | |
| V1.0.4.4 | - | - | - | |

Legend: \
✅ = successfully tested \
? = unknown \
experimental = The support for GS316xxx models is limited to: show port status, power cycle a port, show port settings
`-` = not available \

## download & installation

Expand Down
32 changes: 16 additions & 16 deletions debug_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ func (drc *DebugReportCommand) Run(args *GlobalOptions) error {
args.Verbose = true
model, _, err := readTokenAndModel2GlobalOptions(args, drc.Address)
if err != nil {
println("Warning, prior error: " + err.Error())
fmt.Println("Warning, prior error: " + err.Error())
printDebugNotLoggedIn(args, drc.Address, err)
}
printDebugLoggedIn(args, model, drc.Address)
return nil
}

func printDebugNotLoggedIn(args *GlobalOptions, host string, err error) {
println("---[DEBUG: not logged in]---")
println(fmt.Sprintf("Not logged in error: %s", err))
println("Please try to login and run `debug-report` command again, in order to detect the model and get even more debug information")
fmt.Println("---[DEBUG: not logged in]---")
fmt.Println(fmt.Sprintf("Not logged in error: %s", err))
fmt.Println("Please try to login and run `debug-report` command again, in order to detect the model and get even more debug information")
reqUrls := []string{
fmt.Sprintf("http://%s/", host),
fmt.Sprintf("http://%s/login.cgi", host),
Expand All @@ -31,15 +31,15 @@ func printDebugNotLoggedIn(args *GlobalOptions, host string, err error) {
}
for _, reqUrl := range reqUrls {
body, err := doUnauthenticatedHttpRequestAndReadResponse(args, "GET", reqUrl, "")
println(fmt.Sprintf("---[RESPONSE: %s]---", reqUrl))
fmt.Println(fmt.Sprintf("---[RESPONSE: %s]---", reqUrl))
if err != nil {
println("ERROR: " + err.Error())
fmt.Println("ERROR: " + err.Error())
} else {
println(body)
fmt.Println(body)
}
println("---[/RESPONSE]---")
fmt.Println("---[/RESPONSE]---")
}
println("---[/DEBUG]---")
fmt.Println("---[/DEBUG]---")
}

func printDebugLoggedIn(args *GlobalOptions, model NetgearModel, host string) {
Expand All @@ -66,19 +66,19 @@ func printDebugLoggedIn(args *GlobalOptions, model NetgearModel, host string) {
)
}
if len(reqUrls) > 0 {
println(fmt.Sprintf("---[DEBUG: model '%s']---", model))
fmt.Println(fmt.Sprintf("---[DEBUG: model '%s']---", model))
for _, reqUrl := range reqUrls {
body, err := doHttpRequestAndReadResponse(args, "GET", host, reqUrl, "")
println(fmt.Sprintf("---[RESPONSE: %s]---", reqUrl))
fmt.Println(fmt.Sprintf("---[RESPONSE: %s]---", reqUrl))
if err != nil {
println("ERROR: " + err.Error())
fmt.Println("ERROR: " + err.Error())
} else if checkIsLoginRequired(body) {
println("WARN: it seems the session token expired, please re-login")
fmt.Println("WARN: it seems the session token expired, please re-login")
} else {
println(body)
fmt.Println(body)
}
println("---[/RESPONSE]---")
fmt.Println("---[/RESPONSE]---")
}
println("---[/DEBUG]---")
fmt.Println("---[/DEBUG]---")
}
}
4 changes: 2 additions & 2 deletions formatter_markdown.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package main

import (
"strings"
"fmt"
"strings"
)

func printMarkdownTable(header []string, content [][]string) {
Expand Down Expand Up @@ -33,7 +33,7 @@ func printMarkdownTable(header []string, content [][]string) {
line.WriteString(strings.Repeat("-", l+2)) // a single space for one suffix and one prefix
line.WriteString("|")
}
println(line.String())
fmt.Println(line.String())
line.Reset()

for _, row := range content {
Expand Down
10 changes: 5 additions & 5 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func doHttpRequestAndReadResponse(args *GlobalOptions, httpMethod string, host s
}

if args.Verbose {
println(fmt.Sprintf("send HTTP %s request to: %s", httpMethod, requestUrl))
fmt.Println(fmt.Sprintf("send HTTP %s request to: %s", httpMethod, requestUrl))
}

if isModel316(model) {
Expand Down Expand Up @@ -54,15 +54,15 @@ func doHttpRequestAndReadResponse(args *GlobalOptions, httpMethod string, host s
}
defer resp.Body.Close()
if args.Verbose {
println(resp.Status)
fmt.Println(resp.Status)
}
bytes, err := io.ReadAll(resp.Body)
return string(bytes), err
}

func doUnauthenticatedHttpRequestAndReadResponse(args *GlobalOptions, httpMethod string, requestUrl string, requestBody string) (string, error) {
if args.Verbose {
println("Fetching data from: " + requestUrl)
fmt.Println("Fetching data from: " + requestUrl)
}

req, err := http.NewRequest(httpMethod, requestUrl, strings.NewReader(requestBody))
Expand All @@ -77,10 +77,10 @@ func doUnauthenticatedHttpRequestAndReadResponse(args *GlobalOptions, httpMethod
}
defer resp.Body.Close()
if args.Verbose {
println(resp.Status)
fmt.Println(resp.Status)
for name, values := range resp.Header {
for _, value := range values {
println(fmt.Sprintf("Response header: '%s' -- '%s'", name, value))
fmt.Println(fmt.Sprintf("Response header: '%s' -- '%s'", name, value))
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions login.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func promptForPassword(serverName string) (string, error) {
fmt.Printf("Please enter password for '%s' (input hidden) :> ", serverName)
// the int conversion is required for the windows build to succeed
password, err := term.ReadPassword(int(syscall.Stdin))
println()
fmt.Println()
return string(password), err
}

Expand All @@ -72,7 +72,7 @@ func doLogin(args *GlobalOptions, host string, encryptedPwd string) error {
return errors.New("Unknown model not supported, please contact the developers ")
}
if args.Verbose {
println("login attempt: " + url)
fmt.Println("login attempt: " + url)
}

var formData string
Expand All @@ -88,7 +88,7 @@ func doLogin(args *GlobalOptions, host string, encryptedPwd string) error {
}
defer resp.Body.Close()
if args.Verbose {
println(resp.Status)
fmt.Println(resp.Status)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
Expand Down Expand Up @@ -166,14 +166,14 @@ func getSeedValueFromSwitch(args *GlobalOptions, host string) (string, error) {
return "", errors.New("Unknown model not supported, please contact the developers ")
}
if args.Verbose {
println("fetch seed value from: " + url)
fmt.Println("fetch seed value from: " + url)
}
resp, err := http.Get(url)
if err != nil {
return "", err
}
if args.Verbose {
println(resp.Status)
fmt.Println(resp.Status)
}
defer resp.Body.Close()

Expand Down
8 changes: 4 additions & 4 deletions netgear_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ func isSupportedModel(modelName string) bool {
func detectNetgearModel(args *GlobalOptions, host string) (NetgearModel, error) {
url := fmt.Sprintf("http://%s/", host)
if args.Verbose {
println("detecting Netgear switch model: " + url)
fmt.Println("detecting Netgear switch model: " + url)
}
resp, err := http.Get(url)
if err != nil {
return "", err
}
if args.Verbose {
println(fmt.Sprintf("HTTP response code %d", resp.StatusCode))
fmt.Println(fmt.Sprintf("HTTP response code %d", resp.StatusCode))
}
if resp.StatusCode != 200 {
println(fmt.Sprintf("Warning: response code was not 200; unusual, but will attempt detection anyway"))
fmt.Println(fmt.Sprintf("Warning: response code was not 200; unusual, but will attempt detection anyway"))
}
responseBody, err := io.ReadAll(resp.Body)
_ = resp.Body.Close()
Expand All @@ -57,7 +57,7 @@ func detectNetgearModel(args *GlobalOptions, host string) (NetgearModel, error)
return "", errors.New("Can't auto-detect Netgear model from response. You may try using --model parameter ")
}
if args.Verbose {
println(fmt.Sprintf("Detected model %s", model))
fmt.Println(fmt.Sprintf("Detected model %s", model))
}
return model, nil
}
Expand Down
13 changes: 6 additions & 7 deletions poe_cycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ func (poe *PoeCyclePowerCommand) cyclePowerGs30xEPx(args *GlobalOptions) error {
}

changedPorts := collectChangedPoePortConfiguration(poe.Ports, settings)
prettyPrintSettings(args.OutputFormat, changedPorts)
prettyPrintPoePortSettings(args.model, args.OutputFormat, changedPorts)
return nil
}

func (poe *PoeCyclePowerCommand) cyclePowerGs316EPx(args *GlobalOptions) error {
for _, switchPort := range poe.Ports {
if switchPort < 1 || switchPort > 15 {
return errors.New(fmt.Sprintf("given port id %d, doesn't fit in range 1..15", switchPort))
if switchPort < 1 || switchPort > gs316NoPoePorts {
return errors.New(fmt.Sprintf("given port id %d, doesn't fit in range 1..%d", switchPort, gs316NoPoePorts))
}
}

Expand All @@ -91,7 +91,7 @@ func (poe *PoeCyclePowerCommand) cyclePowerGs316EPx(args *GlobalOptions) error {
return err
}
if args.Verbose {
println(result)
fmt.Println(result)
}
if result != "SUCCESS" {
return errors.New(result)
Expand All @@ -105,14 +105,13 @@ func (poe *PoeCyclePowerCommand) cyclePowerGs316EPx(args *GlobalOptions) error {
statuses = filter(statuses, func(status PoePortStatus) bool {
return slices.Contains(poe.Ports, int(status.PortIndex))
})
prettyPrintStatus(args.OutputFormat, statuses)
prettyPrintPoePortStatus(args.OutputFormat, statuses)
return nil
}

func createPortResetPayloadGs316EPx(poePorts []int) string {
result := strings.Builder{}
const maxPorts = 15 // the port 16 can't be reset
for i := 0; i < maxPorts; i++ {
for i := 0; i < gs316NoPoePorts; i++ {
written := false
for _, p := range poePorts {
if p-1 == i {
Expand Down
Loading

0 comments on commit 6d202d5

Please sign in to comment.