added 4 password options (set passwordOption to 1 or 2 or 3 in code)
-- 0. set password in code
-- 1. ask for password in dialog box -- enter password
-- 2. use keychain to get password -- have to click "allow"
-- 3. sudo without password, works only if fing has been enabled to run without password, see option 3 in code what to do to enable. thanks to "gcoop76"
response time until indigo variable get updated is now: ~ 6 secs for new devices or devices that awake before indigo variable gets updated. -- still 65 sec for devices that go to sleep.
==> checking ling logfile for any changes, logfile gets updated if a devices contacts network (fing is listening to the traffic)
tried to put fing output into indigo sub directory. but is seems that fing does not like spaces in path
tried with ", ' , \" etc creates a error message from fing that input is wrong.
if I don't get any bug reports, next version will be 1.0
Karl
uploaded wrong file.. please use this one.
Code: Select all
-- fingscan.app
-- build list of network devices using FING
-- runs in background, iddles for 5 secs then checks if FING has found new configs
-- creates variables with ipdevice info
--
--
-- Karl Wachs
-- Sep 12 2013
-- V 0.97
-- 0.81 one code fix, if IP number change: wrong quotes for variable
-- 0.82 added comments, clearer code, and reset logfile once a day
-- 0.9 added check logfile for any change, if no chang skip checks, faster reaction, and less code excution, most of the time nothing changes. this will only check size of file "finglog"
-- 0.95 check for change in fingdata file. if time stamp changed get all data and update indigo (1/minute)
-- adding a device results in an update of indigo within 6 secs, detection of disconnecting a debvice takes up to 65 secs. connecting sends traffic, disconnecting in most cases no, have to wait until next ping cycle (1/minute)
-- 0.97 added 4 password options (set passWordOption to 0 or 1 or 2 or 3 see code for details
--
--
-- how to install:
-- copy this script into applescript editor, save into .../indigo 6/scripts/attachments
-- export into …/indigo 6/scripts/attachments as APP with "stay open after run handler.."
-- then start fingscan using finder (doubleclick on fingscan.app in indigo 6/scripts/attachments
--
-- use in indigo as trigger:
-- setup trigger "IPdevice22 down"
-- trigger if any change to ipDevice22
-- condition ipDevice22 must contain ";down" down (without ; )probably also works, but you might have a device's name up or down or vendor's name may contain string up or down
-- action: whatever you like
--
-- what it does:
-- starts fing if not active
-- deletes data and log file before first start, creates file fingdata and finlog in ~/Documnets/
-- will ask for approval to use keychain for sudofing command
-- will run every 5 seconds and check finglog file size, if changed check fingdata file for new info
-- will create/ update varibales ipDevicenn nn = 01 .. 99
-- will update ipDeviceLastUpdate with last date/time of last run
-- will ask for each new MAC address to assign nickname
-- ipDevicenn will contain eg powerONoff;00:04:A3:AD:A5:CB;192.168.1.81;Microchip Technology;up
-- withh powerONoff = nickname, then macaddress, ip, vendor, up/downinfo, date of last change if any
--
-- fing will stay active and will create log file and data file. log file will continuously increase. finglog file is checked for changed file size, fingdata file is analzed by this script
-- regular read seems to conflict with fing, we use cat with pipe into applescript variable.
--
-- needs to be fixed:
-- does not allow non consequtive ipDevice03 ..05 eg 04 missing .. deleted variable
-- tried to put fing output files into indigo directory, but fing does not like spaces in directories, so i put the outputfiles into User/yourid/Documents/fing/ fingdata and finglog
--
--
-- added 4 password options
-- 0. set password in code
-- 1. ask for password in dialog box
-- 2. use keychain to get password
-- 3. sudo without password works only o=if fing has been enabled to run without password, see option 3 in code what to do.
-- uses ~ 0.1-1% of one cpu (mostly 0.1%)
on quit -- enable quit
continue quit
end quit
on run -- this is done only once at time of "open"
global debug
global theDir
global userName
global theFile
global theLog
global lastLogFilesize
global logFilesize
global noOfDevices
global FingContents
global noOfIndigoDevices
global IndigoIpDevices
global lastUpdate
global passwordOption
global yourPassword
set yourPassword to "" -- use this if paaswordOption = 0
set passwordOption to 3 -- 0= set password in code, 1= use keychain to get password, 2 = enabel fing to not require password, 3 = enter password when running
set userName to short user name of (system info)
set theDir to "/Users/" & userName & "/Documents/fing/"
set theFile to "fingdata"
set theLog to "finglog"
set lastLogFilesize to 0
set logFilesize to 0
set newDevice to 0
set lastUpdate to ""
-- init if needed
setupFing()
-- send to idle
idle
-- finish main pgm from now on on idle takes over
end run
on idle -- every 30 seconds this gets executed
global theDir
global userName
global theFile
global theLog
global lastLogFilesize
global logFilesize
global newDevice
global noOfDevices
global FingContents
global noOfIndigoDevices
global IndigoIpDevices
global lastUpdate
set noOfLines to 0
set AppleScript's text item delimiters to {";"}
-- update indigo with time stamp
set theTime to text -8 thru -1 of ((current date) as «class isot» as string)
-- check file size of logfile, if its larger than last time, new data
set cmd to "ls -l " & theDir & theLog & "| awk '{print $5}'"
set logFilesize to do shell script cmd
if logFilesize > lastLogFilesize then -- there must be a new entry in finglog
-- read latest fingdata log file (just last line)
getFingIPlogdata()
if noOfDevices < 1 then -- read not successful .. must be more than 0 devices changed on network
set lastLogFilesize to logFilesize
else -- yes there is really new data to use:
-- use last line of FINGlog for new information
set nextLine to paragraph 1 of FingContents
set theItems to every text item of nextLine
set theLOGIPNumber to item 3 of theItems as text
set theLOGStatus to item 2 of theItems as text
set theLOGDate to item 1 of theItems as text
set theLOGmacAddress to item 6 of theItems as text
set theLOGVendor to item 7 of theItems as text
-- get all devices stored in indigo into IndigoIpDevices, same format as from FING
getIndigoIPDEvices()
-- compare to indogo info
set newDevice to 0
compareToIndigo(theLOGmacAddress, theLOGIPNumber, theLOGVendor, theLOGStatus, theLOGDate)
end if
end if
-- check if fingdata was updated (once a minute)
set cmd to "ls -l " & theDir & theFile & "| awk '{print $8}'" -- time stamp of last change of file
set thisUpdate to do shell script cmd
if not (thisUpdate = lastUpdate) then -- updated FINGdata file
set lastUpdate to thisUpdate -- remember this time stamp
-- read latest fingdata file
getFingIPData()
if noOfDevices > 1 then -- read not successful .. must be more than 1 devices on network
-- get all devices stored in indigo into IndigoIpDevices, same format as from FING
set newDevice to 0
getIndigoIPDEvices()
-- all data read now compare if anything new
set ii to 0
-- loop through FING data
repeat while ii < noOfDevices
set ii to ii + 1
set nextLine to paragraph (ii) of FingContents
set theItems to every text item of nextLine
set themacAddress to item 6 of theItems as text
if not (themacAddress = theLOGmacAddress) then
set theIPNumber to item 1 of theItems as text
set theStatus to item 3 of theItems as text
set theDate to item 4 of theItems as text
set theVendor to item 7 of theItems as text
-- set theAssignedName to item 5 of theItems as text -- not used
-- set theHostName to item 2 of theItems as text -- not used
compareToIndigo(themacAddress, theIPNumber, theVendor, theStatus, theDate)
end if
end repeat
set theTime to text -8 thru -1 of ((current date) as «class isot» as string)
end if
end if
-- house keeping, update ipDeviceLastUpdate and reset logfile once a day
-- update indigo with time stamp
try -- just in case indigo is down, dont crash this program
tell application "IndigoServer"
set the value of variable "ipDevsLastUpdate" to theTime
end tell
end try
return 5 -- idle for 5 seconds
end idle
on setupFing()
global theDir
global theFile
global theLog
global userName
global theIndigoFolder
global passwordOption
global yourPassword
--check if fing is already running, if not start it.
set theApp to "fing.bin"
set theResponse to " "
-- find indigo folder (copied from Nathan Sheldon etrack.app)
set theIndigoFolder to ""
tell application "Finder"
-- Verify one of the supported Indigo versions exists.
set ii to 20
repeat while ii > 1
set theFolder to "/Library/Application Support/Perceptive Automation/Indigo " & ii & "/IndigoServer.app"
if exists theFolder as POSIX file then
set theIndigoFolder to "/Library/Application Support/Perceptive Automation/Indigo " & ii & "/"
set ii to 0
end if
set ii to ii - 1
end repeat
end tell
-- fing dos not handle space in directy names
-- set theDir to theIndigoFolder & "Scripts/Attachments/fingdata/"
-- create fing directory in attachment folder
set cmd to "mkdir '" & theDir & "' >/dev/null 2>&1 & "
do shell script cmd
-- check if fing.bin is running
try
set theResponse to do shell script "ps aux | grep '" & theApp & "' | awk '{print $2}' "
end try
-- if pgmToFind is running then theResponse has 3 lines with PIDs from : ps, fing itself and one more --- have not figured out which one..
set ii to count words of theResponse
if ii < 3 then -- if not running start script, start fing
-- option 0: set thePassword in code
-- start fing, send to background, dont wait, creat 2 output files: one table format file and one logfile
if passwordOption = 0 then
set cmd to "echo " & yourPassword & " | sudo -S fing -o table,csv,\"" & theDir & theFile & "\" log,csv,\"" & theDir & theLog & "\" >/dev/null 2>&1 &"
set yourPassword to ""
end if
-- option 1: have to use sudo: pipe password from getPW() into sudo
-- start fing, send to background, dont wait, creat 2 output files: one table format file and one logfile
if passwordOption = 1 then
set yourPassword to getPW(userName) -- this has to be looked at, grabs first occurence of userName, if 2 with same username and different passwords this might fail
set cmd to "echo " & yourPassword & " | sudo -S fing -o table,csv,\"" & theDir & theFile & "\" log,csv,\"" & theDir & theLog & "\" >/dev/null 2>&1 &"
set yourPassword to ""
end if
-- option 2: modify system setting so that fing does not need sudo from gcoop76 indido discussions
(*
sudo visudo
add this line:
CODE: SELECT ALL
spanky localhost = NOPASSWD: /usr/bin/fing
That is, if "spanky" is your username (the one who will be executing the applescript and calling fing).
Note that this edits the file in "vi." Use the arrow keys or "j" or "k" to move up and down. Go to the line you want to add the above text and hit "i" for insert. Type or paste it out, then hit "esc." Then hit ":" then type "wq" for "write, then quit"
That should do it. It is important to use visudo to edit your sudoers file since apparently bad things can happen to the permissions of the file if you edit it directly. I just tested it on my Mac OS X Mountain Lion laptop. Works well. Everything else still needs a password for sudo, but not fing.
*)
if passwordOption = 2 then
set cmd to " sudo fing -o table,csv,\"" & theDir & theFile & "\" log,csv,\"" & theDir & theLog & "\" >/dev/null 2>&1 &"
set yourPassword to ""
end if
--option 3 user will need to enter password
if passwordOption = 3 then
tell application "Finder" -- need to go through finder in case this runs in the background
set yourPassword to the text returned of (display dialog "enter your password" default answer "xxyyzz" giving up after 200)
end tell
set cmd to "echo " & yourPassword & " | sudo -S fing -o table,csv,\"" & theDir & theFile & "\" log,csv,\"" & theDir & theLog & "\" >/dev/null 2>&1 &"
end if
-- execute option 1,2,3
do shell script cmd
delay 10 --wait until FING has finished at least once
end if
-- fing is running or has started
try -- just in case indigo is down, dont crash this program
set theTime to text -8 thru -1 of ((current date) as «class isot» as string)
tell application "IndigoServer"
if not ((exists variable "ipDevsLastUpdate")) then
make new variable with properties {name:"ipDevsLastUpdate", value:theTime}
end if
end tell
end try
return
end setupFing
on getIndigoIPDEvices()
global noOfIndigoDevices
global IndigoIpDevices
-- get all devices stored in indigo into IndigoIpDevices, same format as from FING
set AppleScript's text item delimiters to {";"}
set ii to 0
set noOfIndigoIpDevices to "0"
set IndigoIpDevices to {}
set noMore to false
repeat while ii < 999
set ii to ii + 1
set OOii to ii
if ii < 10 then set OOii to "0" & ii as text
set ipDevice to "ipDevice" & OOii
tell application "IndigoServer"
if not ((exists variable ipDevice)) then
set noMore to true
set noOfIndigoDevices to ii - 1
set ii to 99999
end if
end tell
if noMore = false then
try -- just in case indigo is down, dont crash this program
tell application "IndigoServer"
set ipDeviceValue to (get value of variable ipDevice) as text
end tell
end try
set IndigoIpDevices to IndigoIpDevices & ipDeviceValue
end if
end repeat
return
end getIndigoIPDEvices
on compareToIndigo(themacAddress, theIPNumber, theVendor, theStatus, theDate)
global noOfIndigoDevices
global IndigoIpDevices
global newDevice
-- then check if any match in indigo data
set sameMAC to 0
set jj to 0
repeat while jj < noOfIndigoDevices
set jj to jj + 1
set nextLineIndigo to item jj of IndigoIpDevices as text
set theIndigoItems to every text item of nextLineIndigo
set indigomacAddress to trim(item 2 of theIndigoItems as text)
if themacAddress = indigomacAddress then ---- mac number found, already in indigo… exit loop
set sameMAC to jj -- this is the device thats the same
set jj to 999999 -- force loop exit
set indigoIPNumber to trim(item 3 of theIndigoItems as text) -- get the indigo info for later use
set indigoStatus to trim(item 5 of theIndigoItems as text)
set indigoVendor to trim(item 4 of theIndigoItems as text)
set indigoNick to trim(item 1 of theIndigoItems as text)
end if
end repeat
if sameMAC > 0 then -- found match in MAC number, now check if anything has changed
-- check if the device that was indicated by the logfile is this one: then reset to normal search
if (theIPNumber = indigoIPNumber) and (theStatus = indigoStatus) then -- both the same
-- do nothing
else -- ip or status has changed, update indigo variable
-- check if the device taht was indicated by the logfile is this one: then reset to normal search
set OOii to sameMAC
if sameMAC < 10 then set OOii to "0" & sameMAC as text -- make sequential number 2 digits
set theDeviceNo to "ipDevice" & OOii
set theDeviceValue to indigoNick & ";" & themacAddress & ";" & theIPNumber & ";" & theVendor & ";" & theStatus & ";" & theDate
try -- just in case indigo is down, dont crash this program
tell application "IndigoServer"
set the value of variable theDeviceNo to theDeviceValue
end tell
end try
end if
else -- new device, set up in indigo
set newDevice to newDevice + 1
set OOii to noOfIndigoDevices + newDevice
if OOii < 10 then set OOii to "0" & ii as text -- make sequential number 2 digits
set theDeviceName to "ipDevice" & OOii
set theText to "FINGSCAN network has found new device, please enter nickname for new device : " & theDeviceName & " " & themacAddress & " " & theIPNumber & " " & theVendor & " " & theStatus & " eg:"
tell application "Finder" -- need to go through finder in case this runs in the background
set nickname to the text returned of (display dialog theText default answer "phone-xyz" giving up after 60)
end tell
set theDeviceValue to nickname & ";" & themacAddress & ";" & theIPNumber & ";" & theVendor & ";" & theStatus & ";" & theDate
try -- just in case indigo is down, dont crash this program
tell application "IndigoServer"
make new variable with properties {name:theDeviceName, value:theDeviceValue}
end tell
end try
end if
end compareToIndigo
on getFingIPData()
global noOfDevices
global FingContents
global theDir
global theFile
set FingContents to {}
-- read latest fingdata file
set cmd to "cat " & theDir & theFile
try
set FingContents to (do shell script cmd)
set noOfDevices to (count paragraphs of FingContents)
end try
return
end getFingIPData
on getFingIPlogdata()
global noOfDevices
global FingContents
global theDir
global theFile
global theLog
set FingContents to {}
set cmd to "tail -1 " & theDir & theLog -- just get the last line
try
set FingContents to (do shell script cmd)
set noOfDevices to (count paragraphs of FingContents)
end try
end getFingIPlogdata
on getPW(keychainItemName) -- get password from keychain for userid: keychainitemname
do shell script "security 2>&1 >/dev/null find-generic-password -gl " & quoted form of keychainItemName & " | awk '{print $2}'"
return (text 2 thru -2 of result) -- return the password part of the string
end getPW
-- trim blanks from string
on trim(someText)
if someText = "" then return someText
if someText = " " then return ""
repeat until someText does not start with " "
set someText to text 2 thru -1 of someText
end repeat
repeat until someText does not end with " "
set someText to text 1 thru -2 of someText
end repeat
return someText
end trim