美文网首页
mac自动连接wifi

mac自动连接wifi

作者: RadishHuang | 来源:发表于2023-04-02 14:14 被阅读0次

文字描述比较少,有遇到问题可以V本人。

公司wifi需要登录认证网页,手动输入账号和密码,验证完成后,才能开始上网。如果电脑合盖,或者睡眠。再次打开需要重新在打开网页,输入账号密码,连接。就和我们在KFC或者是机场、酒店,连接了wifi会弹出一个认证的窗口。

image.png
  • 首先想到的是把url的请求地址拿出来,通过curl的请求去完成认证。
    这个有一个问题是当Captive Network Assistant弹出的时候,网络会被拦截,这个英语翻译成中文的意思强制网络助理。只要有这个弹窗在,网络都会被终止(没有实际性的原理,亲测是网络被拦截)

  • 最早是使用sleepwatcher来执行,当mac唤醒的时候,执行脚本。
    有个问题就是当切换网络的时候,就没办法执行脚本了。只能在唤起的时候使用

解决方案

使用hammerspoon+lua+applescript来解决

思路

  • 监听网络切换和电脑的唤醒、解锁
  • 监听到事件,查找是否有目标wifi在,如果有,强制连接目标wifi
  • 监听Captive Network Assistant的弹窗,如果弹窗存在,执行applescript的脚本,自动输入账号密码

安装hammerspoon

  • 使用brew安装
没有安装过brew的话可以先执行
/usr/bin/ruby -e "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/homebrew-install/install)"
然后安装
brew install hammerspoon --cask
  • 下载app,自行百度或者官网下载。这边就不做更多的说明
  • 安装完成后,顶部会有一个锤子的图标,点击红框部分给到权限。可以开机的时候就启动hammerspoon
image.png
  • 小技巧,可以把图标也隐藏。通过command + 空格,唤起搜索,搜索ha开头,可以再打开设置界面。


    image.png
    image.png
  • 在~目录下可以看到有这个文件。hammerspoon会先执行init.lua


    image.png

开发环境

init.lua 判断了如果是自己的mac,才会执行自动更新脚本。这样只要有修改,hammerspoon的控制台就会有log,方便做调试

require "wifi.wifi"

if (hs.host.localizedName() == 'Radish') then
    
local pathwatcher = require "hs.pathwatcher"  
local alert = require "hs.alert"
-- 开启自动重载配置文件
function autoReload()  
  function reloadConfig(files)
      doReload = false
      for _, file in pairs(files) do
          if file:sub(-4) == ".lua" then
              doReload = true
          end
      end
      if doReload then
          hs.reload()
      end
  end
  pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon", reloadConfig):start()
end

autoReload()  
end

wifi

wifi的脚本思路和上面所述的一样。主要监听了监听电脑休眠和唤醒wifi发生改变创建应用程序监控器。唤醒的时候,去扫描后台有没有目标WIFINAME,有的话,就连接目标wifi,执行applescript脚本



local WIFINAME = "Dianei";
-- local USERNAME = "1111"
-- local PASSWORD = "2222"

-- 异步执行shell
function asyncSheel(cmd, callback)
  hs.task.new("/bin/sh", function(exitCode, stdOut, stdErr)
    if exitCode ~= 0 then
      print("Error executing command: " .. stdErr)
      callback()
    else
      print("Command output: " .. stdOut)
      callback(stdOut)
    end
  end, {"-c", cmd}):start()
end

-- 执行shell脚本
function shell(cmd)
  local success,obj,descriptor = hs.osascript.applescript(string.format('do shell script "%s"', cmd))
  return success,obj,descriptor
end

-- 判断网络是否连接
function isNet()
  local success,obj,descriptor = shell("ping -o -t 1 baidu.com")
  if (success and obj ~= nil and string.find(descriptor, '1 packets received')~= nil) then
    return true
  else
    return false
  end
end


function wifiCallback(watcher, message, interface)
  local ssid = hs.wifi.currentNetwork(interface)
    if (ssid ~= nil and ssid == WIFINAME) then
      print("当前wifi列表中存在"..ssid)
      -- scan()
    end
end


function caffeinateCallback(event)
  if event == hs.caffeinate.watcher.screensDidSleep then
    -- 屏幕休眠(屏保开启)
    print("screensDidSleep")
  elseif event == hs.caffeinate.watcher.screensDidWake then
    -- 屏幕唤醒
    print("screensDidWake")
  elseif event == hs.caffeinate.watcher.screensDidLock then
    print("screensDidLock")
  elseif event == hs.caffeinate.watcher.screensDidUnlock then
    -- 屏幕解锁
    print("screensDidUnlock")
    -- 强制开启wifi的按钮
    asyncSheel("networksetup -setairportpower en0 on", function()
      print('强制开启了wifi按钮')
      -- 后台扫描WiFi热点
      hs.wifi.backgroundScan(function(networks)
        -- 处理扫描结果
        print("wifi 扫描完成")
        for i, network in ipairs(networks) do
            if (network.ssid == WIFINAME or network.bssid == WIFINAME) then
              print("找到 wifi名字了")
              -- 连接wifi 等待cna的弹窗
              hs.wifi.associate(WIFINAME, "")
              break
            end
        end
      end)
    end)
  elseif event == hs.caffeinate.watcher.systemWillSleep then    
    print("systemWillSleep")
  elseif event == hs.caffeinate.watcher.systemDidWake then
    print("systemDidWake")
  elseif event == hs.caffeinate.watcher.systemWillPowerOff then
    print("systemWillPowerOff")
  elseif event == hs.caffeinate.watcher.systemDidPowerOn then
    print("systemDidPowerOn")
  end
end

-- 应用程序激活事件处理
function applicationCallback(name, event, app)
  -- and event == hs.application.watcher.launched
  if name == "Captive Network Assistant" or name == "强制网络助理"  then
    -- 启动
    -- print(hs.application.watcher.launched)
    -- -- 激活
    -- print(hs.application.watcher.activated)
    -- 在 Captive Network Assistant 打开时自动输入账号密码
    if event == hs.application.watcher.activated then
      print("激活cna了 ~ ")
      asyncSheel("osascript ~/.hammerspoon/wifi/cna.applescript", function(e)
        print("执行完毕")
        local haveNet = isNet()
        if (haveNet == true) then
          hs.alert.show(WIFINAME.."网络已连接")
        end
      end)
    end
  end
end

-- 监听电脑休眠和唤醒
hs.caffeinate.watcher.new(caffeinateCallback):start()
-- wifi发生改变
hs.wifi.watcher.new(wifiCallback):start()
-- 创建应用程序监控器
hs.application.watcher.new(applicationCallback):start()



function getDianneiWifi()
  return hs.window.filter.new(false):setAppFilter("Captive Network Assistant", { currentSpace = true, allowTitles = "加入“Dianei”" }):getWindows()
end



-- hs.application:getWindow(title)


-- function launchOrNextWindow(name, showName)
--  local findName = showName or name
--  local appName = hs.application.frontmostApplication():name()
--  print("appName")
--  print(appName)
--  if findName ~= appName then
--          hs.application.launchOrFocus(name)
--  else
--          -- local wlist = getWinList(findName)
--          -- local wcount = #wlist
--          -- if wcount > 1 then
--          --      hs.eventtap.keyStroke({'cmd'}, '`')
--          -- else
--          --      local win = wlist[1]
--          --      if win:isMinimized() then win:unminimize() else win:minimize() end
--          -- end
--  end
-- end

-- function mapLaunch(key, name, showName)
--  hs.hotkey.bind({}, key, function()
--          launchOrNextWindow(name, showName)
--  end)
-- end

-- mapLaunch('f1', 'Google Chrome')
-- launchOrNextWindow('iTerm', 'iTerm2')

applescript

需要注意的是,vscode中默认是UTF-8的编码,applescript要设置为GB2312。不然有中文的会识别不了


global WIFINAME
global USERNAME
global USERPASSWORD
global ROOPNUM
global DELAYTIME
global NOTWIFI
set WIFINAME to "xxxx"
set USERNAME to "xxx"
set USERPASSWORD to "xxxx"
set ROOPNUM to 5
set DELAYTIME to 0.5

set roopCount to 0
repeat while roopCount < ROOPNUM
    if isNet() = true then
        log "net connct success"
        my closeDianei()
        exit repeat
    else
        if my getCNAAlert() = 1 then
            log "find cna"
            -- begin connect
            my connectWIFI()
        end if
        set roopCount to roopCount + 1
    end if
end repeat




on closeDianei()
    tell application "System Events"
        -- 是否存在 CNA 弹窗
        if exists (process "Captive Network Assistant") then
            -- 进入CNA的进程
            tell process "Captive Network Assistant"
                -- 是否存在dianei的wifi连接弹窗
                if exists (window "加入“Dianei”") then
                    -- 进入dianeiwif连接的弹窗
                    tell window "加入“Dianei”"
                        -- 进入UI界面
                        if exists (button "完成") then
                            click button "完成"
                        end if
                        if exists (button "取消") then
                            click button "取消"
                        end if
                    end tell
                end if
            end tell
        end if
    end tell
end closeDianei



on getCNAAlert()
    -- 系统事件
    tell application "System Events"
        if exists (process "Captive Network Assistant") then
            return 1
        else
            return 2
        end if
    end tell
end getCNAAlert


on connectWIFI()
    -- 系统事件
    tell application "System Events"
        -- 是否存在 CNA 弹窗
        if exists (process "Captive Network Assistant") then
            -- 进入CNA的进程
            tell process "Captive Network Assistant"
                -- 是否存在dianei的wifi连接弹窗
                if exists (window "加入“Dianei”") then
                    -- 进入dianeiwif连接的弹窗
                    tell window "加入“Dianei”"
                        -- 进入UI层级 从这个命令去找 entire contents  找到对应想要的名称。比如用户名 密码 注销等等
                        if exists (UI element 1 of scroll area 1 of group 1 of group 2) then
                            -- UI层架
                            tell UI element 1 of scroll area 1 of group 1 of group 2
                                set groupTag to 0
                                repeat while groupTag < 50
                                    try
                                        if my isNet() = true then
                                            exit repeat
                                        else
                                            if exists (text field 1 of group 1 of group groupTag) then
                                                log "开始自动输入用户名和密码"
                                                -- 用户名
                                                tell group 1 of group groupTag
                                                    set value of attribute "AXFocused" of text field 1 to true
                                                    set value of text field 1 to USERNAME
                                                end tell
                                                -- 密码
                                                tell group 2 of group groupTag
                                                    set value of attribute "AXFocused" of text field 1 to true
                                                    set value of text field 1 to USERPASSWORD
                                                end tell
                                                -- 勾选框
                                                tell group (groupTag + 1)
                                                    click checkbox 1
                                                end tell
                                                -- 登录按钮
                                                tell group (groupTag + 2)
                                                    click button "登录"
                                                end tell
                                                exit repeat
                                            else
                                                set groupTag to groupTag + 1
                                            end if
                                        end if
                                    end try
                                end repeat
                            end tell
                        end if
                    end tell
                end if
            end tell
        end if
    end tell
end connectWIFI



on isNet()
    try
        set pingResult to do shell script "ping -o -t 1 baidu.com"
        if pingResult contains "1 packets received" then
            return true
        else
            return false
        end if
    on error
        return false
    end try
end isNet

相关文章

网友评论

      本文标题:mac自动连接wifi

      本文链接:https://www.haomeiwen.com/subject/erlrddtx.html