feat: add network interface selection to CLI tools
onvif-cli improvements: - Add menu option to list network interfaces - Add interface selection during discovery - Display detailed interface information (up/down, multicast, addresses) - Allow discovery by interface name or IP address - Maintain backward compatibility with default interface onvif-quick improvements: - Add menu option to list network interfaces - Add interface selection during discovery - Simplified interface list display - Quick discovery on specific network Documentation: - Add comprehensive CLI_NETWORK_INTERFACE_USAGE.md guide - Include usage scenarios and workflows - Troubleshooting section - Integration examples - Command reference table These enhancements allow users to easily specify which network interface to use for camera discovery, solving issues with multi-interface systems.
This commit is contained in:
+99
-11
@@ -36,14 +36,16 @@ func main() {
|
||||
case "1":
|
||||
cli.discoverCameras()
|
||||
case "2":
|
||||
cli.connectToCamera()
|
||||
cli.listNetworkInterfaces()
|
||||
case "3":
|
||||
cli.deviceOperations()
|
||||
cli.connectToCamera()
|
||||
case "4":
|
||||
cli.mediaOperations()
|
||||
cli.deviceOperations()
|
||||
case "5":
|
||||
cli.ptzOperations()
|
||||
cli.mediaOperations()
|
||||
case "6":
|
||||
cli.ptzOperations()
|
||||
case "7":
|
||||
cli.imagingOperations()
|
||||
case "0", "q", "quit", "exit":
|
||||
fmt.Println("Goodbye! 👋")
|
||||
@@ -58,14 +60,15 @@ func main() {
|
||||
func (c *CLI) showMainMenu() {
|
||||
fmt.Println("📋 Main Menu:")
|
||||
fmt.Println(" 1. Discover Cameras on Network")
|
||||
fmt.Println(" 2. Connect to Camera")
|
||||
fmt.Println(" 2. List Network Interfaces")
|
||||
fmt.Println(" 3. Connect to Camera")
|
||||
if c.client != nil {
|
||||
fmt.Println(" 3. Device Operations")
|
||||
fmt.Println(" 4. Media Operations")
|
||||
fmt.Println(" 5. PTZ Operations")
|
||||
fmt.Println(" 6. Imaging Operations")
|
||||
fmt.Println(" 4. Device Operations")
|
||||
fmt.Println(" 5. Media Operations")
|
||||
fmt.Println(" 6. PTZ Operations")
|
||||
fmt.Println(" 7. Imaging Operations")
|
||||
} else {
|
||||
fmt.Println(" 3-6. (Connect to camera first)")
|
||||
fmt.Println(" 4-7. (Connect to camera first)")
|
||||
}
|
||||
fmt.Println(" 0. Exit")
|
||||
fmt.Println()
|
||||
@@ -87,14 +90,99 @@ func (c *CLI) readInputWithDefault(prompt, defaultValue string) string {
|
||||
return input
|
||||
}
|
||||
|
||||
func (c *CLI) listNetworkInterfaces() {
|
||||
fmt.Println("🌐 Available Network Interfaces")
|
||||
fmt.Println("================================")
|
||||
|
||||
interfaces, err := discovery.ListNetworkInterfaces()
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Error listing interfaces: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(interfaces) == 0 {
|
||||
fmt.Println("❌ No network interfaces found")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("✅ Found %d interface(s):\n\n", len(interfaces))
|
||||
|
||||
for _, iface := range interfaces {
|
||||
upStr := "⬆️ Up"
|
||||
if !iface.Up {
|
||||
upStr = "⬇️ Down"
|
||||
}
|
||||
|
||||
multicastStr := "✓"
|
||||
if !iface.Multicast {
|
||||
multicastStr = "✗"
|
||||
}
|
||||
|
||||
fmt.Printf("📡 %s (%s, Multicast: %s)\n", iface.Name, upStr, multicastStr)
|
||||
|
||||
if len(iface.Addresses) == 0 {
|
||||
fmt.Println(" (No addresses assigned)")
|
||||
} else {
|
||||
for _, addr := range iface.Addresses {
|
||||
fmt.Printf(" └─ %s\n", addr)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
fmt.Println("💡 Use interface name or IP address when discovering cameras")
|
||||
fmt.Println(" Example: eth0 or 192.168.1.100")
|
||||
}
|
||||
|
||||
|
||||
func (c *CLI) discoverCameras() {
|
||||
fmt.Println("🔍 Discovering ONVIF cameras...")
|
||||
fmt.Println("This may take a few seconds...")
|
||||
|
||||
// Ask user if they want to select a specific network interface
|
||||
useSpecificInterface := c.readInput("Use specific network interface? (y/n) [n]: ")
|
||||
useSpecificInterface = strings.ToLower(useSpecificInterface)
|
||||
|
||||
var opts *discovery.DiscoverOptions
|
||||
if useSpecificInterface == "y" || useSpecificInterface == "yes" {
|
||||
fmt.Println("\nAvailable network interfaces:")
|
||||
interfaces, err := discovery.ListNetworkInterfaces()
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Error listing interfaces: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
for i, iface := range interfaces {
|
||||
fmt.Printf(" %d. %s\n", i+1, iface.Name)
|
||||
for _, addr := range iface.Addresses {
|
||||
fmt.Printf(" └─ %s\n", addr)
|
||||
}
|
||||
multicastStr := "No"
|
||||
if iface.Multicast {
|
||||
multicastStr = "Yes"
|
||||
}
|
||||
fmt.Printf(" (Up: %v, Multicast: %s)\n", iface.Up, multicastStr)
|
||||
}
|
||||
|
||||
ifaceInput := c.readInput("\nEnter interface name or IP address: ")
|
||||
ifaceInput = strings.TrimSpace(ifaceInput)
|
||||
|
||||
if ifaceInput != "" {
|
||||
opts = &discovery.DiscoverOptions{
|
||||
NetworkInterface: ifaceInput,
|
||||
}
|
||||
fmt.Printf("🎯 Using interface: %s\n\n", ifaceInput)
|
||||
}
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = &discovery.DiscoverOptions{}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
devices, err := discovery.Discover(ctx, 5*time.Second)
|
||||
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Discovery failed: %v\n", err)
|
||||
return
|
||||
|
||||
+84
-6
@@ -22,9 +22,10 @@ func main() {
|
||||
for {
|
||||
fmt.Println("What would you like to do?")
|
||||
fmt.Println("1. 🔍 Discover cameras")
|
||||
fmt.Println("2. 📹 Connect to camera")
|
||||
fmt.Println("3. 🎮 PTZ demo")
|
||||
fmt.Println("4. 📡 Get stream URLs")
|
||||
fmt.Println("2. 🌐 List network interfaces")
|
||||
fmt.Println("3. 📹 Connect to camera")
|
||||
fmt.Println("4. 🎮 PTZ demo")
|
||||
fmt.Println("5. 📡 Get stream URLs")
|
||||
fmt.Println("0. Exit")
|
||||
fmt.Print("\nChoice: ")
|
||||
|
||||
@@ -35,10 +36,12 @@ func main() {
|
||||
case "1":
|
||||
discoverCameras()
|
||||
case "2":
|
||||
connectAndShowInfo()
|
||||
listNetworkInterfaces()
|
||||
case "3":
|
||||
ptzDemo()
|
||||
connectAndShowInfo()
|
||||
case "4":
|
||||
ptzDemo()
|
||||
case "5":
|
||||
getStreamURLs()
|
||||
case "0", "q", "quit":
|
||||
fmt.Println("Goodbye! 👋")
|
||||
@@ -51,12 +54,48 @@ func main() {
|
||||
}
|
||||
|
||||
func discoverCameras() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Println("🔍 Discovering cameras on network...")
|
||||
|
||||
// Ask if user wants to use a specific interface
|
||||
fmt.Print("Use specific network interface? (y/n) [n]: ")
|
||||
useInterface, _ := reader.ReadString('\n')
|
||||
useInterface = strings.ToLower(strings.TrimSpace(useInterface))
|
||||
|
||||
var opts *discovery.DiscoverOptions
|
||||
if useInterface == "y" || useInterface == "yes" {
|
||||
// List interfaces
|
||||
interfaces, err := discovery.ListNetworkInterfaces()
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("\nAvailable interfaces:")
|
||||
for i, iface := range interfaces {
|
||||
fmt.Printf(" %d. %s (%v)\n", i+1, iface.Name, iface.Addresses)
|
||||
}
|
||||
|
||||
fmt.Print("\nEnter interface name or IP: ")
|
||||
ifaceInput, _ := reader.ReadString('\n')
|
||||
ifaceInput = strings.TrimSpace(ifaceInput)
|
||||
|
||||
if ifaceInput != "" {
|
||||
opts = &discovery.DiscoverOptions{
|
||||
NetworkInterface: ifaceInput,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = &discovery.DiscoverOptions{}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
devices, err := discovery.Discover(ctx, 5*time.Second)
|
||||
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Error: %v\n", err)
|
||||
return
|
||||
@@ -73,6 +112,45 @@ func discoverCameras() {
|
||||
}
|
||||
}
|
||||
|
||||
func listNetworkInterfaces() {
|
||||
fmt.Println("🌐 Network Interfaces")
|
||||
fmt.Println("====================")
|
||||
|
||||
interfaces, err := discovery.ListNetworkInterfaces()
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(interfaces) == 0 {
|
||||
fmt.Println("No network interfaces found")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("✅ Found %d interface(s):\n\n", len(interfaces))
|
||||
|
||||
for _, iface := range interfaces {
|
||||
upStr := "Up"
|
||||
if !iface.Up {
|
||||
upStr = "Down"
|
||||
}
|
||||
|
||||
multicastStr := "Yes"
|
||||
if !iface.Multicast {
|
||||
multicastStr = "No"
|
||||
}
|
||||
|
||||
fmt.Printf("📡 %s (%s, Multicast: %s)\n", iface.Name, upStr, multicastStr)
|
||||
|
||||
if len(iface.Addresses) > 0 {
|
||||
for _, addr := range iface.Addresses {
|
||||
fmt.Printf(" └─ %s\n", addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func connectAndShowInfo() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user