Router Wi-Fi Password Change & Display

@QMcKay, it varies from one router to another. Most of them support Telnet. New routers support SSH. With SSH, you will need the to use the key if you want to run an auto command, command line are also different from one router to another.

Just use putty to do the scripting.

I have a solution, but it’s a bit ugly.

I’m having to build a .sh dynamically on-the-fly using .bat file echo statements, because I can’t figure out how to retrieve the parameters/arguments (i.e. $1 $2) in the .sh script when executed as such…

plink.exe -ssh %rHOST% -P %rPORT% -l %rUSER% -pw %rPW% -m "script.sh" "ARG1 ARG2"

The above works with either PUTTY or PLINK, however, in script.sh, the arguments are missing… that is, $1, $2, etc. are empty. Anyone know how to send them through PLINK (or PUTTY) so they are available to script.sh?


The BAT file _wifi_change_guest1.bat dynamically builds _wifi_change_guest1.sh which is subsequently passed to PLINK.

@echo off
cls

set rHOST=192.168.0.1
set rPORT=23
set rUSER=admin
set rPASS=<router admin password>
set rGUEST24net1=wl0.1_wpa_psk
set rGUEST50net1=wl1.1_wpa_psk
set rGUESTpw1=%1
set rSCRIPT=_wifi_change_guest1.sh
set LOGFILE=_LOGFILE_Router.txt

:: go to where PLINK is located    
C:
CD\
CD C:\D\Programs\POS\router

:: Delete previous LOGFILE
if exist %LOGFILE% del %LOGFILE%

:: Delete previous rSCRIPT
if exist %rSCRIPT% del %rSCRIPT%

:: Build the Script into file %rSCRIPT% using ECHO statements
echo #!/bin/sh> %rSCRIPT%
echo guestnet241=%rGUEST24net1%>> %rSCRIPT%
echo guestnet501=%rGUEST50net1%>> %rSCRIPT%
echo guestpw1=%rGUESTpw1%>> %rSCRIPT%
echo echo ---------->> %rSCRIPT%
echo echo Shell Script BEG>> %rSCRIPT%
echo echo >> %rSCRIPT%
echo echo n241 $guestnet241>> %rSCRIPT%
echo echo n501 $guestnet501>> %rSCRIPT%
echo echo pwch $guestpw1>> %rSCRIPT%
echo echo >> %rSCRIPT%

echo echo ---------->> %rSCRIPT%
echo echo CURRENT password for $guestnet241 ...>> %rSCRIPT%
echo nvram show ^| grep $guestnet241>> %rSCRIPT%
echo echo >> %rSCRIPT%
echo echo Changing password for $guestnet241 to -$guestpw1- ...>> %rSCRIPT%
echo nvram set $guestnet241=$guestpw1>> %rSCRIPT%
echo echo >> %rSCRIPT%
echo echo NEW password for $guestnet241 ...>> %rSCRIPT%
echo nvram show ^| grep $guestnet241>> %rSCRIPT%
echo echo ---------->> %rSCRIPT%
echo echo >> %rSCRIPT%

echo echo ---------->> %rSCRIPT%
echo echo CURRENT password for $guestnet501 ...>> %rSCRIPT%
echo nvram show ^| grep $guestnet501>> %rSCRIPT%
echo echo >> %rSCRIPT%
echo echo Changing password for $guestnet501 to -$guestpw1- ...>> %rSCRIPT%
echo #nvram set $guestnet501=$guestpw1>> %rSCRIPT%
echo echo >> %rSCRIPT%
echo echo NEW password for $guestnet501 ...>> %rSCRIPT%
echo nvram show ^| grep $guestnet501>> %rSCRIPT%
echo echo ---------->> %rSCRIPT%
echo echo >> %rSCRIPT%

echo echo Shell Script END>> %rSCRIPT%
echo echo ---------->> %rSCRIPT%
echo echo exiting...>> %rSCRIPT%
echo exit>> %rSCRIPT%

@echo on
:: Run %rSCRIPT% through PLINK
plink.exe -ssh %rHOST% -P %rPORT% -l %rUSER% -pw %rPASS% -m "%rSCRIPT%" >> %LOGFILE% 2>&1

::@notepad %LOGFILE%
::timeout 1

::pause

:end

The SH file _wifi_change_guest1.sh (dynamically built on-the-fly by above .BAT file):

#!/bin/sh
guestnet241=wl0.1_wpa_psk
guestnet501=wl1.1_wpa_psk
guestpw1=newpassword
echo ----------
echo Shell Script BEG
echo 
echo n241 $guestnet241
echo n501 $guestnet501
echo pwch $guestpw1
echo 
echo ----------
echo CURRENT password for $guestnet241 ...
nvram show | grep $guestnet241
echo 
echo Changing password for $guestnet241 to -$guestpw1- ...
nvram set $guestnet241=$guestpw1
echo 
echo NEW password for $guestnet241 ...
nvram show | grep $guestnet241
echo ----------
echo 
echo ----------
echo CURRENT password for $guestnet501 ...
nvram show | grep $guestnet501
echo 
echo Changing password for $guestnet501 to -$guestpw1- ...
#nvram set $guestnet501=$guestpw1
echo 
echo NEW password for $guestnet501 ...
nvram show | grep $guestnet501
echo ----------
echo 
echo Shell Script END
echo ----------
echo exiting...
exit

The Log file _LOGFILE_Router.txt indicates success:

----------
Shell Script BEG

n241 wl0.1_wpa_psk
n501 wl1.1_wpa_psk
pwch newpassword

----------
CURRENT password for wl0.1_wpa_psk ...
size: 42019 bytes (23517 left)
wl0.1_wpa_psk=abracadabra

Changing password for wl0.1_wpa_psk to -newpassword- ...

NEW password for wl0.1_wpa_psk ...
size: 42016 bytes (23520 left)
wl0.1_wpa_psk=newpassword
----------

----------
CURRENT password for wl1.1_wpa_psk ...
size: 42016 bytes (23520 left)
wl1.1_wpa_psk=

Changing password for wl1.1_wpa_psk to -newpassword- ...

NEW password for wl1.1_wpa_psk ...
size: 42016 bytes (23520 left)
wl1.1_wpa_psk=
----------

Shell Script END
----------
exiting...

Action Start Process AC Run Script WiFi

Name: AC Run Script WiFi
Type: Start Process
File Name: C:\D\Programs\POS\router\_wifi_change_guest1.bat
Arguments: {:WiFiPW}
Use Shell Execute: False
Is Hidden: False (or True)


PuTTY Setup (also required when using PLINK):

The setup shown above is required when using SSH, to store the Router rsa2 Fingerprint in the registry. This applies to using PuTTY or PLINK on the command-line with SSH connections, and is only required to be run once. Also, this lets you alternatively call the saved SessionName on the command-line, instead of using the Hostname or IP, as such:

putty.exe -load "mysession"

instead of:

putty.exe -ssh HOSTNAMEorIP

This might help:

I’m excited to see the final solution :slight_smile:

Alternatively it might be possible to generate sh file by using a printer template.

Thanks for that @neko, though what is suggested in that thread doesn’t work in this case.

$ plink user@10.220.60.xx -t /home/user/test/testpgm arg1

This is because plink is being called from the Shell (indicating it is available to the system), while in my case, I’m calling plink from Windows CMD.

Another suggestion I found was this (plink being called from CMD):

plink -T ... $SHELL /dev/stdin arg1 arg2 arg3 < hello.sh

I think the above may work, though I currently get an error to the effect of “can't find /dev/stdin”. Probably because stdin isn’t located in /dev/, rather somewhere else on the router, but I don’t know how to find it’s location. What command can I issue on the router to find a file? I’ve never been much good at *nix command line :wink:

Let me see if I understand the methodology you’re eluding to @emre.

Do you mean to say create a Printer that prints to File (i.e. script.sh), and execute a Print Job using a Template that contains the commands I want to execute?

Interesting… that may be a little more elegant. I will give that a try!

1 Like

Ok @emre, I gave this a try, but something strange is going on that I don’t understand.

Here is a portion of the Printer Template:

    #!/bin/sh
    guestnet241=wl0.1_wpa_psk
    guestnet501=wl1.1_wpa_psk
    guestpw1={:WiFiPW}

If I set up an Automation Command called Router Script and map it to Ticket, then have an Action to Execute the Print Job, which prints to wifichange.sh, and a Rule, then the contents of the file is:

#!/bin/sh
guestnet241=wl0.1_wpa_psk
guestnet501=wl1.1_wpa_psk
guestpw1=abracadabra

Ok, so far so good. It also works if the Automation Command is on a Custom Entity Screen (i.e. my Table Screen). However, if I place the Automation Command on an Account Screen (i.e. General, which is where I like it to be), the {:WiFiPW} setting is being ignored (it’s not being evaluated), so the file contents are:

#!/bin/sh
guestnet241=wl0.1_wpa_psk
guestnet501=wl1.1_wpa_psk
guestpw1={:WiFiPW}

Can you tell me why this is the case? Can I fix it?

I couldn’t understand how {:WiFiPW} tag worked :slight_smile:

Inside template it should be configured as {SETTING:WiFiPW} if it stored as a setting.

I’ve always referenced the Program setting for WiFiPW as {:WiFiPW} in rules, actions, and Templates (it works just fine). I changed it to {SETTING:WiFiPW} (thank-you for providing the correct syntax) in the Template, and it also works when the Command is on the Ticket or Custom (Table) Entity Screen.

However, when the Command is on an Account screen, {SETTING:WiFiPW} isn’t being evaluated, so the output to the .sh file stays as {SETTING:WiFiPW}, instead of the content of the WiFiPW Program Setting, which happens to be “abracadabra”.

This is being written to the .sh file:

#!/bin/sh
guestnet241=wl0.1_wpa_psk
guestnet501=wl1.1_wpa_psk
guestpw1={SETTING:WiFiPW}

The above only occurs when executing the Command from an Account screen. When executing from the Ticket Screen, or Entity Screen, the file correctly contains:

#!/bin/sh
guestnet241=wl0.1_wpa_psk
guestnet501=wl1.1_wpa_psk
guestpw1=abracadabra

@emre, I really want this to work on an Account Screen, and I love the use of the Template rather than the abomination of a .BAT file that I originally posted. The Template is so much more elegant and simple. @emre, is there something I"m missing here, or do I need to wait for an updated version?

Hello @QMcKay. I’ve setup a demo environment to be able to reproduce your issue and I found that printer templates does not work if there is no active ticket. I’ve enabled non ticket related tags for reading settings, date and random numbers. It will work for next version. I’m waiting for an update for the management navigation bar touch issue. I’ll release new version as soon as I receive the update.

1 Like

Thanks for that @emre. Eagerly awaiting :wink: Much appreciated!

Hi @QMcKay, I tested and it works as below:

$ plink user@x.x.x.x "command arg"

@neko, that probably works with a command that is available on the host, but when you want to send a script from windows CMD, the host reports that the script cannot be found, and so is the case when you try to send the script with or without parameters.

Execute from Windows CMD:

plink.exe -v -ssh -P %rPORT% -pw %rPASS% %rUSER%@%rHOST% "wifichange.sh" > %LOGFILE% 2>&1

gives output (from host):

sh: wifichange.sh: not found

I am happy to report that as of v4.1.39, I can access a Program Setting from the Account Screen.

That said, the following works:

{:WiFiPW}

While the following does not (it isn’t being evaluated, and stays as {SETTING:WiFiPW}):

{SETTING:WiFiPW}

Ok, I need to clarify this a bit, because it’s confusing now. @emre, you may want to take a look into this…

As of v4.1.39, I can access a Program Setting from the Account Screen. Yes, great! However

When used in a Rule or as an Argument to Start Process Action, the following works:

{:WiFiPW}

While the following does not (it isn’t being evaluated, and stays as {SETTING:WiFiPW}):

{SETTING:WiFiPW}

And then it’s backwards in the following case…
When used in a Printer Template, the following works:

{SETTING:WiFiPW}

While the following does not (it isn’t being evaluated, and stays as {:WiFiPW}):

{:WiFiPW}

Here is the currently working setup.

It does not use a Printer Template, and does not use a .sh file. I found the .sh file to be very unreliable when through PLINK.

The Automation Command can be placed virtually anywhere: on the Ticket, on an Entity Screen, or on an Account Screen (as of v4.1.39).

This set up only uses the following .bat file (and some Actions and Rules of course).


::::: SETUP Begin ::::::::::::::::::::

BAT file: _wifi_change_guest1.bat
Updated 2014-06-30 to contain some error checking on the supplied new password.

@echo off
cls

::
:: Set Router Information
::
set rHOST=192.168.0.1
set rPORT=23
set rUSER=admin
set rPASS=<router administrative password>

::
:: Set WiFi Network Information as found in NVRAM
::
set rGUEST24net1=wl0.1_wpa_psk
set rGUEST24net2=wl0.2_wpa_psk
set rGUEST24net3=wl0.3_wpa_psk
set rGUEST50net1=wl1.1_wpa_psk
set rGUEST50net2=wl1.2_wpa_psk
set rGUEST50net3=wl1.3_wpa_psk

::
:: Set a LOGFILE and ERRMSG
::
set LOGFILE=_LOGFILE_Router.txt
set ERRMSG=

::
:: Go to PLINK location
::
C:
CD\
CD C:\D\Programs\POS\router


::
:: Set variables for new passwords (get the %1 argument and use it for all networks)
::
set newpass=%1

::
:: Start Logging
::
@echo. >> %LOGFILE% 2>&1
@echo ******************************************************* >> %LOGFILE% 2>&1
@echo -- BAT BEG ----------------- %date%_%time:~0,2%.%time:~3,2%.%time:~6,2% >> %LOGFILE% 2>&1


::
:: Check password variable to ensure it is Ok
::
IF [%newpass%] NEQ [] @echo Password is not blank
IF [%newpass%] == [] set ERRMSG=ERROR:Password is BLANK
IF [%newpass%] == [] goto ERRORPROCESS

IF "%newpass:~7,1%"=="" (
  set ERRMSG=ERROR:Password less than 8 characters
  goto ERRORPROCESS
) ELSE (
  @echo Password is at least 8 characters
)

set PAT=SETTING
echo.%newpass% | findstr /C:"%PAT%" 1>nul
if errorlevel 1 (
  @echo Password does not Contain Printer Template Tag '%PAT%'
) ELSE (
  set ERRMSG=ERROR:Password contains Printer Template Tag' %PAT%'
)
set errorlevel=

set PAT="^{"
echo.%newpass% | findstr /C:"%PAT%" 1>nul
if errorlevel 1 (
  @echo Password does not Contain Printer Template 'Start Tag'
) ELSE (
  set ERRMSG=%ERRMSG% ERROR:Password contains Printer Template 'Open Tag'
)
set errorlevel=

set PAT="^}"
echo.%newpass% | findstr /C:"%PAT%" 1>nul
if errorlevel 1 (
  @echo Password does not Contain Printer Template 'End Tag'
) ELSE (
  set ERRMSG=%ERRMSG% ERROR:Password contains Printer Template 'Close Tag'
)
set errorlevel=

set PAT="^:"
echo.%newpass% | findstr /C:"%PAT%" 1>nul
if errorlevel 1 (
  @echo Password does not Contain Printer Template 'Separator'
) ELSE (
  set ERRMSG=%ERRMSG% ERROR:Password contains Printer Template 'Separator'
)
set errorlevel=


::
:: If there is a problem with the given password, %ERRMSG% will contain a value, and we abandon the script
::
IF "%ERRMSG%" NEQ "" GOTO ERRORPROCESS


::
:: If password variable is Ok, we continue...
::
::
:: Set variables for new passwords (get the %1 argument and use it for all networks)
::
set pw24_1=%newpass%
set pw24_2=%newpass%
set pw24_3=%newpass%
set pw50_1=%newpass%
set pw50_2=%newpass%
set pw50_3=%newpass%


::
:: Set up Commands
::
set cShowNets="nvram show | grep wl..._wpa_psk | sort | sed 's/wl/\r\nwl/g'"
set cCommitNVRAM="nvram commit"
set cRESTARTwifi="service restart_wireless"
set cREBOOT="reboot"
set cSetNet24_1="nvram set %rGUEST24net1%=%pw24_1%"
set cSetNet24_2="nvram set %rGUEST24net2%=%pw24_2%"
set cSetNet24_3="nvram set %rGUEST24net3%=%pw24_3%"
set cSetNet50_1="nvram set %rGUEST50net1%=%pw50_1%"
set cSetNet50_2="nvram set %rGUEST50net2%=%pw50_2%"
set cSetNet50_3="nvram set %rGUEST50net3%=%pw50_3%"


::
:: Show us what we are about to do
::
@echo rHOST: %rHOST%
@echo rPORT: %rPORT%
@echo pw24_1: %pw24_1%
@echo pw50_1: %pw50_1%




::
:: Run COMMANDS through PLINK
::
@echo on

:: If we get this far, it's time to run the commands to the Router
@echo -- ROUTER CHANGE BEG ------- %date%_%time:~0,2%.%time:~3,2%.%time:~6,2% >> %LOGFILE% 2>&1
@echo rHOST: %rHOST%>> %LOGFILE% 2>&1
@echo rPORT: %rPORT%>> %LOGFILE% 2>&1
@echo net24_1: %rGUEST24net1%>> %LOGFILE% 2>&1
@echo net50_1: %rGUEST50net1%>> %LOGFILE% 2>&1
@echo pwd24_1: %pw24_1%>> %LOGFILE% 2>&1
@echo pwd50_1: %pw50_1%>> %LOGFILE% 2>&1
@echo.>> %LOGFILE% 2>&1

:: Show CURRENT Passwords
@echo ----- Guest Networks CURRENT ...>> %LOGFILE% 2>&1
plink.exe -ssh %rHOST% -P %rPORT% -l %rUSER% -pw %rPASS% -batch %cShowNets% >> %LOGFILE% 2>&1
@echo.>> %LOGFILE% 2>&1

:: Set the Passwords for the desired Networks and Commit NVRAM
@echo ----- SETTING NEW PASSWORDS ...>> %LOGFILE% 2>&1
:: this line currently sets GuestNetwork #1 for both 2.4GHz and 5.0GHz bands and commits them to NVRAM
:: add more Networks if so desired (i.e. cSetNet24_2), and ensure the cCommitNVRAM command is retained
plink.exe -ssh %rHOST% -P %rPORT% -l %rUSER% -pw %rPASS% -batch %cSetNet24_1% %cSetNet50_1% %cCommitNVRAM% >> %LOGFILE% 2>&1
@echo.>> %LOGFILE% 2>&1

:: Show UPDATED Passwords
@echo ----- Guest Networks UPDATED ...>> %LOGFILE% 2>&1
plink.exe -ssh %rHOST% -P %rPORT% -l %rUSER% -pw %rPASS% -batch %cShowNets% >> %LOGFILE% 2>&1
@echo.>> %LOGFILE% 2>&1
@echo.>> %LOGFILE% 2>&1

:: Restart the WIFI Service for new passwords to take effect
@echo ----- RESTARTING WIFI SERVICE ...>> %LOGFILE% 2>&1
plink.exe -ssh %rHOST% -P %rPORT% -l %rUSER% -pw %rPASS% -batch %cRESTARTwifi% >> %LOGFILE% 2>&1
@echo.>> %LOGFILE% 2>&1

:: End Router Changes
@echo -- ROUTER CHANGE END ------- %date%_%time:~0,2%.%time:~3,2%.%time:~6,2% >> %LOGFILE% 2>&1

@echo off



::
:: We are almost done. Test for Errors.
::
IF [%ERRMSG%] == [] GOTO finished


:ERRORPROCESS
@echo %ERRMSG% 
@echo %ERRMSG% >> %LOGFILE% 2>&1 
@echo -- BAT END ----------------- %date%_%time:~0,2%.%time:~3,2%.%time:~6,2% >> %LOGFILE% 2>&1
:: Open the LOGFILE
@notepad %LOGFILE%
goto endoffile


:finished
@echo -- BAT END ----------------- %date%_%time:~0,2%.%time:~3,2%.%time:~6,2% >> %LOGFILE% 2>&1


:endoffile
::
:: We are done.  Uncomment the following lines if you wish.
::

::@notepad %LOGFILE%

::timeout 2
::pause

Automation Command - WiFiPW Update

Automation Command can be mapped as a button (i.e. to the Ticket screen), or no mapping is necessary if you want to place it on an Entity Screen or Account Screen.

Name: AU WiFiPW Update
Button Header: Change WiFi )))
Mappings: (choose what is suitable for your setup)


Action: Update Program Setting

Name: AC WiFiPW Update Program Setting
Type: Update Program Setting
Setting Name: WiFiPW
Setting Value: [:WiFiPW]
Update Type: Update
Is Local: False

Action: Start Process

Name: AC WiFiPW Update Start BAT Script
Type: Start Process
File Name: C:\D\Programs\POS\Router\_wifi_change_guest1.bat
Arguments: [:args]
Use Shell Execute: False
Is Hidden: True

Rule: Update Program Setting and Run BAT file

Name: RU WiFiPW Update
Event: Automation Command Executed
Constraints: Execute rule if Matches
Automation Command Name Equals AU WiFiPW Update

Actions:

Name: AC WiFiPW Update Program Setting
Constraint:
WiFiPW: [?Enter New WiFi Password (8 characters minimum):([a-zA-Z0-9]{8,26})]

Name: AC WiFiPW Update Start BAT Script
Constraint:
args: {:WiFiPW}

::::: SETUP End ::::::::::::::::::::


The Rule captures the click-event of the Automation Command.

First, it fires an Action to Update Program Setting WiFiPW, which asks for input with the prompt “Enter New WiFi Password (8 characters minimum)”. The input box has a mask ([a-zA-Z0-9]{8,26}) which ensures the entered value contains only Alpha-Numeric characters [a-zA-Z0-9], and ensures the value is more than 7 characters and less than 27 characters {8,26}.

Second, it fires the Action Start Process which runs the .bat file.

The .bat file should produce the following log:

Log File: _LOGFILE_Router.txt

******************************************************* 
-- BAT BEG ----------------- 2014-06-30_13.18.56 
-- ROUTER CHANGE BEG ------- 2014-06-30_13.18.57 
rHOST: 192.168.0.1
rPORT: 23
net24_1: wl0.1_wpa_psk
net50_1: wl1.1_wpa_psk
pwd24_1: str0ngpa55word
pwd50_1: str0ngpa55word

----- Guest Networks CURRENT ...
size: 41946 bytes (23590 left)
wl0.1_wpa_psk=goodfriends
wl0.2_wpa_psk=
wl0.3_wpa_psk=
wl1.1_wpa_psk=goodfriends
wl1.2_wpa_psk=
wl1.3_wpa_psk=

----- SETTING NEW PASSWORDS ...

----- Guest Networks UPDATED ...
size: 41952 bytes (23584 left)
wl0.1_wpa_psk=str0ngpa55word
wl0.2_wpa_psk=
wl0.3_wpa_psk=
wl1.1_wpa_psk=str0ngpa55word
wl1.2_wpa_psk=
wl1.3_wpa_psk=

----- RESTARTING WIFI SERVICE ...
Done.
-- ROUTER CHANGE END ------- 2014-06-30_13.19.09 
-- BAT END ----------------- 2014-06-30_13.19.09 

Awesome!!! It automates a common issue really well.

Now I’m wondering what can be an alternative to placing such functions to accounting screen.

We can also improve it by configuring a printer template to print wifi password. When asked waiter can simply print password from bill printer and give it to customer.

I think this works exactly how it implemented.

Since Rules can read Printer template tags these tags are interchangeable in some cases but correct usage is {:WiFiPW} to read setting from rules and {SETTING:WiFiPW} to print.

1 Like

Ok, good. I thought this may be by design. It’s just something to keep in mind when using Program Settings.

You may be able to guess the reasons I want the button(s) on an Account Screen.

  • The POS Ticket Screen already has a lot of buttons, can get crowded, and Changing WiFi Password isn’t related to a Ticket in the first place.
  • When we End WorkPeriod, the POS Ticket Screen and Entity Screens are no longer available/enabled, but the Account Screen is still enabled. It also makes sense to have buttons like Calculator and Open Drawer on an Account Screen, so we can perform Cashout Duties or Payouts to Vendor/Expense Accounts, or even Customer Account functions.

Perhaps if we had another Section in Navigation Screen called Tools or Toolbox which would be available at all times (via Permission), even when no WorkPeriod is is open, we could place Widgets (Automation Commands) on this screen, similar to a Custom Entity Screen.

2 Likes