如何在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
相关产品推荐
相关产品推荐

