Match printer URI from ippfind with a printer listed in lpstat -p?

@robertfern - Thank you. I didn’t know about the arp command. But the output from it doesn’t tell me anything that lets me identify which printer in the lpstat list is the same as a printer in the ippfind list. For example:

arp LJ-P3015-Edward.local
? (192.168.1.25) at 5c:b9:1:13:ef:70 on en0 ifscope [ethernet]

Am I missing something obvious?

Yes.
When you run the lpstat command you get output with a line below

device for HP_LaserJet_Pro_M402n: ipp://192.168.26.200/ipp/print

notice it has an ip address

next when you run the ippfind command you’ll get a line like below

ipp://LJ-P3015-Edward.local:631/LJ-P3015-Edward

notice it has a domain name instead of an IP address.

use “arp LJ-P3015-Edward.local” to get the ip address

the rest should be academic

@robertfern - Unfortunately, I get this output from lpstat:

device for HP_LaserJet_P3010_Series: dnssd://HP%20LaserJet%20P3010%20Series%20%5B13EF70%5D._printer._tcp.local./BINPS

And this from ippfind:

ipp://LJ-P3015-Edward.local:631/LJ-P3015-Edward

Possibly this is because I’m on Sonoma. I had tried exactly this method at the start, but as you see, it doesn’t work.

OK, so run the arp command on both
‘arp HP%20LaserJet%20P3010%20Series%20%5B13EF70%5D._printer._tcp.local’
and
‘arp LJ-P3015-Edward.local’

then compare the ip addresses

@robertfern - Here’s the output. I don’t think it points to a solution:

edward@MacBookAirM2 ~ % arp LJ-P3015-Edward.local
? (192.168.1.25) at 5c:b9:1:13:ef:70 on en0 ifscope [ethernet]
edward@MacBookAirM2 ~ % arp HP%20LaserJet%20P3010%20Series%20%5B13EF70%5D._printer._tcp.local
arp: HP%20LaserJet%20P3010%20Series%20%5B13EF70%5D._printer._tcp.local: Unknown host
```

I just realized you haver the wrong line from your lpstat command.
The line should contain “ipp://”

my printer shows “device for HP_LaserJet_Pro_M402n: ipp://192.168.26.200/ipp/print”

my ippfind command returns “ipp://NPI0458AF.local:631/ipp/print idle accepting-jobs none”

i then ran “arp NPI0458AF.local” and got back the ip address which matched the lpstat

here is the full output from ‘lpstat -l -p -v’…

printer HP_LaserJet_Pro_M402n is idle. enabled since Tue Jan 2 18:01:12 2024
Form mounted:
Content types: any
Printer types: unknown
Description: HP LaserJet Pro M402n
Alerts: none
Location:
Connection: direct
Interface: /private/etc/cups/ppd/HP_LaserJet_Pro_M402n.ppd
On fault: no alert
After fault: continue
Users allowed:
(all)
Forms allowed:
(none)
Banner required
Charset sets:
(none)
Default pitch:
Default page size:
Default port settings:
device for HP_LaserJet_Pro_M402n: ipp://192.168.26.200/ipp/print

i’m assuming if it doesn’t have “ipp://” then its not an ipp printer

@robertfern - All of my printers are listed as both ipp:// printers in the output of ippfind and as dnssd:// printers in the output of lpstat. Here are the relevant lines again:

From lpstat:

device for HP_LaserJet_P3010_Series: dnssd://HP%20LaserJet%20P3010%20Series%20%5B13EF70%5D._printer._tcp.local./BINPS

From ippfind:

ipp://LJ-P3015-Edward.local:631/LJ-P3015-Edward

I have had that printer for twelve years, and I can assure you that it is the same printer under different name The LaserJet Pro P3015 is identified in the browser interface as “LaserJet_P3010_series”. They really are the same.

The same situation occurs with all my other printers. None have an ipp:// address in lpstat; all have an ipp:// address in ippfind.

Hmmm.
I just thought of something.
Did you add the printers using bonjour or did you hardcode the ip addresses?
Mine was hardcoded and I chose ipp as the protocol
I believe the dnssd means it’s bonjour

@robertfern - I simply let macOS System Settings find the printer on the network and set it up. I don’t know whether macOS uses Bonjour to set it up. I’m trying to write a utility for other people to use - I don’t need it myself - and I assume that other people will let macOS find the printer in the same way I did.

Is there anything to be found using the dns-sd utility?

I don’t have a printer hooked up so I can’t test anything (and I don’t understand some of this especially well).

e.g.

% dns-sd -B _services._dns-sd._udp

I was just researching this exact command.

Here was a website talking about it
https://apple.stackexchange.com/questions/175241/how-can-i-list-the-ip-addresses-of-all-the-airprint-printers-on-a-network

@Mockman - Thank you. Unfortunately, the dns-sd command doesn’t give any information that isn’t available more quickly from lpstat and Ippfind.

1 Like

@robertfern - That is the page where I first learned about the ippfind command…

Think I figured it out
When I type 'ippfind -l -s ’ i get

ipp://NPI0458AF.local:631/ipp/print idle accepting-jobs none
HP LaserJet M402n

and when I type ‘lpstat -l -p -v’ i get as the last line

device for HP_LaserJet_M402n: dnssd://HP%20LaserJet%20M402n._ipps._tcp.local./?uuid=50484248-4c37-3839-3534-e4e7490458af

The device matches the last line of ippfind, but with the spaces replaced with underscores

Thank you for this. Unfortunately it doesn’t work on my system. Two problems:

  1. ippfind -l-s only finds two of the three printers on my network; ippfind finds all three.

  2. For the printers that it does find, the match doesn’t occur (it may occur by default, but not if you gave the printer a different name when setting it up in macOS):

device for Cheryl_LaserJet_400_MFP_M425dn: dnssd://Cheryl%20LaserJet%20400%20MFP%20M425dn._ipp._tcp.local./?uuid=434e4638-4837-5139-4b4d-5820b14df350

and

ipp://LJ-M425dn-Cheryl.local:631/ipp/print idle accepting-jobs

I finally think I did it.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property ippfind : missing value
property lpstat : missing value

set ippfind to get_ippfind()
set lpstat to get_lpstat()
-- both list of lists will have the last item be the IP address so you can compare/search the two

on get_ippfind()
	local raw, Printers, MAC, aURL, dn, arp, tid
	set tid to text item delimiters
	set raw to paragraphs of (do shell script "ippfind -l -s")
	set Printers to {}
	repeat with i from 2 to count raw by 2
		set text item delimiters to {"ipp://", ":"}
		set aURL to item (i - 1) of raw
		set dn to text item 2 of aURL
		try
			set arp to do shell script "arp " & dn & " 2>&1"
		on error errMsg number errNum
			set arp to errMsg
		end try
		set text item delimiters to {"(", ")"}
		set end of Printers to {aURL, item i of raw, dn, text item 2 of arp}
	end repeat
	set text item delimiters to tid
	return Printers -- the last item of each printer is the IP address
end get_ippfind

on get_lpstat()
	local raw, Printers, MAC, arp, tid
	set tid to text item delimiters
	set raw to do shell script "lpstat -l -p -v"
	set text item delimiters to "device for "
	set Printers to rest of (text items of raw)
	set arp to paragraphs of (do shell script "arp -a")
	repeat with p in Printers
		set text item delimiters to ":"
		set tmp to text items of p
		set contents of p to {item 1 of tmp, (rest of tmp) as text}
		if item 2 of p starts with " dnssd:" then
			set MAC to text -12 thru -1 of item 2 of p -- last 12 digits are the MAC address
			set MAC to {text 1 thru 2 of MAC, text 3 thru 4 of MAC, text 5 thru 6 of MAC, text 7 thru 8 of MAC, text 9 thru 10 of MAC, text 11 thru 12 of MAC}
			repeat with i from 1 to 6
				if (text 1 of item i of MAC) = "0" then set item i of MAC to text 2 of item i of MAC
			end repeat
			set MAC to MAC as text
			set end of p to MAC
			repeat with i in arp -- find the MAC address in the arp table to find the IP
				set i to contents of i
				if i contains MAC then
					set text item delimiters to {"(", ")"}
					set end of p to text item 2 of i
					exit repeat
				end if
			end repeat
		else if item 2 of p starts with " socket:" then
			set text item delimiters to {"socket://", "/"}
			set end of p to text item 2 of item 2 of p
		end if
	end repeat
	set text item delimiters to tid
	return Printers -- the last item of each printer is the IP address
end get_lpstat

@robertfern - This is truly heroic, and I think it’s almost there, but this version has a few problems on my system.

First, the command ippfind -l -s is interactive and never gets to the third IP printer on my system, so the script never gets past that command. I removed the two parameters, and the script runs, but the outut from ippfind doesn’t have any IP addresses.

Second, the lpstat' list of lists doesn't seem to have IP addresses in the third item. Here are some of the strings it finds on my system, each one followed by an \r`:

82:b:14:df:35:
ca:82:a0:8:c0:f
8d:8d:17:c2:68:c
oc:al:./:BI:NP:S

The last one is fairly clearly part of a string that included local.

The ipfind list has three entries, and the lpstat list has nine, which is correct - three printers are available here. I think we’re close to a way of matching them, but not quite there.

Again, thank you for your heroic efforts on this!

When you run ippfind without the options, what does it return?

lpstat has the IP in the 4th item, not the third. The 3rd has the MAC address

If you are using ‘ippfind’ like this then the code below for method “get_ippfind()”

on get_ippfind()
	local raw, Printers, MAC, aURL, dn, arp, tid
	set tid to text item delimiters
	set raw to paragraphs of (do shell script "ippfind")
	set Printers to {}
	repeat with i from 1 to count raw --by 2
		set text item delimiters to {"ipp://", ":"}
		set aURL to item i of raw
		set dn to text item 2 of aURL
		try
			set arp to do shell script "arp " & dn & " 2>&1"
		on error errMsg number errNum
			set arp to errMsg
		end try
		set text item delimiters to {"(", ")"}
		set end of Printers to {aURL, dn, text item 2 of arp}
	end repeat
	set text item delimiters to tid
	return Printers -- the last item of each printer is the IP address
end get_ippfind

Now each printer only has 3 items, the third being the ip address

The ipp section correctly returns IP addresses in the 192.168. range, but the lpstat returns these as the third item (I’m only listing the ones that match an ippfind printer:

82:b:14:df:35:
8d:8d:17:c2:68:c
oc:al:./:BI:NP:S

Possibly Sonoma does things differently from earlier versions?

Lpstat returns the ip in the 4th item.
I don’t understand your error is.