You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dart中获取设备内网IPv4适配连锁门店SSH管理

问题:Dart脚本无法获取本地内网IPv4,导致无法自动匹配门店POS网段

背景

  • 开发开源Dart脚本,用于通过SSH连接连锁批发门店的Linux POS收银机,简化运维工作
  • 门店内网IP规则:门店n对应网段192.168.n.xxx,POS机固定IP范围为201-253(254为网关)
  • 核心需求:脚本自动获取运行设备的内网IPv4第三段数值,生成对应门店的POS IP列表,无需员工手动选择门店,避免跨门店操作(各门店VPN隔离)

当前代码

import 'dart:io';
import 'package:dart_ipify/dart_ipify.dart';

void main() async{

  final ipfull = await Ipify.ipv4();
  List<String> splitip = ipfull.split('.');
  print('IPV4: $ipfull');
  print('IPV4 in parts: $splitip');

  print('Functions: P (Power ON)     R (Reboot)     O (PowerOff)');

  String? function = stdin.readLineSync();

  List<dynamic> pdvs = [];

  print('Enter the POS numbers and type "e" to end and "c" to'
      'make a correction to an added POS');

  while (true) {
    String? input = stdin.readLineSync();
    if (input == 'e') {
      break;
    } else if(input == 'c') {
      print('What number do you want to remove?');
      String? inputc = stdin.readLineSync();
      pdvs.remove(inputc);
    } else if (input == 'v') {
      print("Current list: $pdvs");
    } else {
      pdvs.add(input);
    }
  }

  if(function == 'l'){
    print('Turning on POS $pdvs');
  } else if(function == 'r'){
    print('Restarting POS $pdvs');
    for(String p in pdvs){
      print('192.168.10.2$p');
    }
  } else if(function == 'd'){
    print('Turning OFF POS $pdvs');
  } else{
    print('unknown function');
  }

}

核心问题

dart_ipify是用于获取公网IP的工具,调用Ipify.ipv4()返回的是Fortigate网关IP,而非运行脚本设备的本地内网IPv4,无法通过splitip[2]提取门店网段的第三段数值,导致无法自动匹配对应门店的POS IP范围。

解决方案

1. 替换内网IP获取方式

改用dart:io的NetworkInterface枚举本地网卡,筛选出192.168开头的内网IPv4地址:

// 替换原ipify相关代码
String? localIp;
await for (var interface in NetworkInterface.list()) {
  for (var addr in interface.addresses) {
    if (addr.type == InternetAddressType.IPv4 && addr.address.startsWith('192.168.')) {
      localIp = addr.address;
      break;
    }
  }
  if (localIp != null) break;
}

if (localIp == null) {
  print('无法获取内网IPv4地址');
  exit(1);
}

List<String> splitip = localIp.split('.');
print('内网IPV4: $localIp');
print('IP分段: $splitip');
String storeSegment = splitip[2]; // 提取门店网段第三段

2. 修正其他逻辑问题

  • 统一功能输入判断:原提示为P/R/O,代码判断同步改为p/r/o(兼容大小写)
  • 修正POS IP生成逻辑:根据POS机201-253的范围,将输入数字转换为最后一段IP(输入1对应201,输入2对应202)
  • 规范列表类型:将List<dynamic> pdvs改为List<String> pdvs避免类型错误
  • 增加输入校验:过滤非数字的无效输入

修改后的完整代码

import 'dart:io';

void main() async{

  // 获取本地内网IPv4
  String? localIp;
  await for (var interface in NetworkInterface.list()) {
    for (var addr in interface.addresses) {
      if (addr.type == InternetAddressType.IPv4 && addr.address.startsWith('192.168.')) {
        localIp = addr.address;
        break;
      }
    }
    if (localIp != null) break;
  }

  if (localIp == null) {
    print('无法获取内网IPv4地址');
    exit(1);
  }

  List<String> splitip = localIp.split('.');
  print('内网IPV4: $localIp');
  print('IP分段: $splitip');
  String storeSegment = splitip[2];

  // 功能选择
  print('Functions: P (Power ON)     R (Reboot)     O (PowerOff)');
  String? function = stdin.readLineSync()?.toLowerCase();

  // 收集POS编号
  List<String> pdvs = [];
  print('输入POS编号(1对应201,2对应202...),输入"e"结束,"c"删除已添加项,"v"查看当前列表');

  while (true) {
    String? input = stdin.readLineSync();
    if (input == 'e') {
      break;
    } else if(input == 'c') {
      print('输入要删除的编号:');
      String? inputc = stdin.readLineSync();
      pdvs.remove(inputc);
    } else if (input == 'v') {
      print("当前POS列表: $pdvs");
    } else if (input != null && int.tryParse(input) != null) {
      pdvs.add(input);
    } else {
      print('无效输入,请输入数字或指定指令');
    }
  }

  // 执行对应操作
  if(function == 'p'){
    print('正在开机POS:$pdvs');
    pdvs.forEach((p) {
      int lastOctet = 200 + int.parse(p);
      print('目标IP: 192.168.$storeSegment.$lastOctet');
      // 此处添加SSH开机逻辑
    });
  } else if(function == 'r'){
    print('正在重启POS:$pdvs');
    pdvs.forEach((p) {
      int lastOctet = 200 + int.parse(p);
      print('目标IP: 192.168.$storeSegment.$lastOctet');
      // 此处添加SSH重启逻辑
    });
  } else if(function == 'o'){
    print('正在关机POS:$pdvs');
    pdvs.forEach((p) {
      int lastOctet = 200 + int.parse(p);
      print('目标IP: 192.168.$storeSegment.$lastOctet');
      // 此处添加SSH关机逻辑
    });
  } else{
    print('未知功能指令');
  }

}

内容的提问来源于stack exchange,提问作者Nevyle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:25:42