mac自动连接wifi

文字描述比较少,有遇到问题可以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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容