ZeroConf/Bonjour Library

Status
Not open for further replies.
The interesting thing is that the communications chain you described actually does not involve a single bit of AppleSpeak. The protocols involved are generic printer protocols and TCP/IP based protocols and not Apple specific. Zeroconf/Bonjour also is an entirely open and license free standard.
I could explain that, but the book I have linked to in my previous post explains that so much better than I could already on the first pages that I'd like to refer to it. Even though is was published in 2006, with the internet of things upon us it is very up-to-date and well worth the read.

Is the WiFi bridge the same hardware as the AP just configured once as an AP and once a a Bridge or is it really a different hardware device ?
It would be a pretty rare occasion, but possibly the bridge does not support mDNS or it has to be enabled specifically ?
 
The interesting thing is that the communications chain you described actually does not involve a single bit of AppleSpeak. The protocols involved are generic printer protocols and TCP/IP based protocols and not Apple specific. Zeroconf/Bonjour also is an entirely open and license free standard.
I could explain that, but the book I have linked to in my previous post explains that so much better than I could already on the first pages that I'd like to refer to it. Even though is was published in 2006, with the internet of things upon us it is very up-to-date and well worth the read.

Is the WiFi bridge the same hardware as the AP just configured once as an AP and once a a Bridge or is it really a different hardware device ?
It would be a pretty rare occasion, but possibly the bridge does not support mDNS or it has to be enabled specifically ?
WiFi bridge is/was a Buffalo Bridge + switch all in one.
Access point is an ASUS RT-N-D12
I suppose the problem is that something related to Bonjour that is sent on the LAN as ethernet packets, not as IP or ICMP, doesn't (but should?) propagate through the Buffalo Bridge but does pass through the Access Point.

The reason I commented on Apple's printer scheme is (naive as I've not owned a MAC but do own an iPad)... To print from the iPad there are no printer driver/interface software available. I either had to own an "Apple Airprint" compatible printer (which my Epson 630 AIO is not), or I found that my Synology NAS could placate the iPad on the left hand and print on the Epson via the LAN on the right hand. Apple store's suggestion was to replace my perfectly good Epson AIO (1 yr old) and get a "newer" printer with Apple-Airprint capability. Still, there's that absurd lack of print only page 1-n on the overpriced iPad. But I should not complain, I used Visa card points to buy it. ;)

AirPrint
AirPrint is an Apple technology that lets you create full-quality printed output without the need to download or install drivers. AirPrint is built in to many printer models from most popular printer manufacturers. Just select an AirPrint printer on your local network and print from your favorite iOS or OS X app
 
Last edited:
Apples Airprint is an extension of the IPP protocol (Internet Printing Protocol) and there are a number of software approaches that will turn a non Airprint compatible printer into a compatible one. A number of NAS run Linux for example and Linux uses the same printer system as Mac OSX called CUPS.
AirPrint, BTW also uses Bonjour to find the printer service and on Mac OSX one of the possible ways to make a legacy printer Airprint compatible is to simply create a new bonjour service for it.

One can only assume why the Apple store did not suggest any of that.

Back to the topic. I had tried service discovery by connecting the WIZ820io per cable directly to the Airport Express WiFi router but the results (or lack thereof ) were the same. I can see mDNS response packages running Wireshark on my mac. That includes response packages from my Teensy++2-WIZ812MJ combo also running the Bonjour library, so I know that the mDNSresponder part of the Bonjour library also works. It's "only" the part that reads the response packages that seems not to work as expected.

I'd love to have some better debugging abilities then inserting Serial.println() all over the code!
 
Last edited:
May/may-not be relevant..
At my home, when I tried to run the iPAD printing (no special iPad software), it worked fine from iPad WiFi to WiFi access point connected to MoCA (IP over TV Coax) to ethernet switch to NAS. On the NAS is software that converts Apple-speak from the iPad into open standards formats from the NAS to the Epson printer/scanner - which does not have integrated Apple compatibility.

But, when the iPad talks via WiFi to a WiFi BRIDGE product, rather than a WiFi Access Point (AP), the iPad says: No printer found. Odd, because an AP is a form of bridge.

( wasting a lot of paper, because the iPad lacks the choice of print only selected pages).

Well...after all, as it turns out, it is somewhat relevant.
I ocured to me that I never tried to get service discovery with the original version WITHOUT the WiFi router in between. So I just used a virgin copy of the library on an Arduino Uno with Ethernet Shield cabled directly into the Airport Express and service discovery works flawlessly.

So slowly but surely I am closing in on getting this library updated and more or less hardware independent!
 
Last edited:
So I've got it registering and discovering Bonjour services fine on a Teensy++2 <-> WIZ812MJ only using calls to the UDP/EthernetUDP methods.

The following code snippet compiles and runs fine on the Teensy++2 but when trying to compile it for the Teensy 3 the compiler complains about the last line "ptr = ...."
"this->read()" refers to the EthernetUDP "read" method

Code:
uint16_t peer_port, udp_len, ptr, qCnt, aCnt, aaCnt, addCnt

...

udpBuffer = (uint8_t*) malloc(udp_len);  //allocate memory to hold _remaining UDP packet
this->read((uint8_t*)udpBuffer, udp_len);//read _remaining UDP packet from W5100/W5200 into memory
ptr = (uint16_t)udpBuffer;
with
Code:
error: cast from 'uint8_t* {aka unsigned char*}' to 'uint16_t {aka short unsigned int}' loses precision [-fpermissive]

How do I get this to work with Teensy++2 and Teensy 3.x ?

I am happy to have gotten this far but I am out of ideas for the day ;-)
 
The problem is that while on the teensy++2 a pointer is only 16 bits (so you can use a uint16_t to hold a pointer), on the teensy3 a pointer is 32 bits, so a uint16_t can't be used to hold a pointer anymore.

Change the type of your variable ptr to be a proper pointer, rather than a uint16_t and this problem should go away for you (and you won't have to worry about juggling the type you use based on what platform you're compiling on).
 
Thanks a bunch! I had come across this before but unfortunately just could not remember :

Code:
ptr = (uintptr_t)udpBuffer;

The above compiled fine. We'l see if it works but I have not doubt it will.
 
Did you also change the type of the ptr variable as well? You're going to run into problems if you try to stuff a 32-bit pointer (those high 16 bits are sometimes important!) into a 16 bit value, depending on what portion of the address space malloc is playing in.
 
No, of course I had not and naturally it did not work.

Fixed now though and it does work! Thanks again!

I need to clean the lib up some and will publish next week.
 
I've committed a new version of the EthernetBonjour library to my GitHub repository.

This version completely replaces all of the direct hardware calls to the W5100 methods in W5100.cpp. These have been replaced with calls to the UDP/EthernetUDP methods, which provides a much better upgrade path to use the library with different Ethernet hardware. There has been talk about a CC3100 from Texas Instruments that hopefully fixes some of the mistakes that TI made with the CC3000, e.g. the incomplete mDNS implementation.

This new version has been tested with :
Teensy++2 <-> WIZ812MJ and the original PRJC adapter.
Teensy 3 <-> WIZ820io on my own adapter board.

This has been tested with Arduino 1.0.5 IDE and Teensyduino 1.18

Each of the four provided Examples work with the above 2 boards and Ethernet Modules. This implies that mDNS (served registration) and DNS-SD (service discovery) work out of the box. As the Ethernet library that ships with Teensyduino auto detects which Ethernet chip is connected no changes have to be made to either of the samples. You pock your board in the Arduino IDE and compile/upload and it just works. ZeroConf^2 ;-)

H.O.W.E.V.E.R.....

Getting this to work flawlessly I needed to add a few lines to two of the files in the Ethernet library itself:

The EthernetUDP.cpp only has a EthernetUDP.begin() method but a EthernetUDP.beginMulti() method was needed to get multicast UDP, the basis for the Bonjour library to work so this was added to EthernetUDP.h:

Code:
virtual uint8_t beginMulti(IPAddress, uint16_t);	// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use Sending UDP packets
.
.
.
friend class EthernetBonjourClass;

Consequently here's the method that was added to EthernetUDP.cpp:

Code:
/* Start EthernetUDP socket, listening at local port PORT */
uint8_t EthernetUDP::beginMulti(IPAddress ip, uint16_t port) {

  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    uint8_t s = W5100.readSnSR(i);
    if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
      _sock = i;
      break;
    }
  }

  if (_sock == MAX_SOCK_NUM)
    return 0;

  byte mac[] = {  0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 };

  mac[3] = ip[1] & 0x7F;
  mac[4] = ip[2];
  mac[5] = ip[3];

//  byte mac[] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb };

  W5100.writeSnDIPR(_sock, rawIPAddress(ip));
  W5100.writeSnDPORT(_sock, port);
  W5100.writeSnDHAR(_sock,mac);

  _remaining = 0;

  socket(_sock, SnMR::UDP, port, SnMR::MULTI);

  return 1;
}

I am hoping that these additions will make it into one of the next Teensyduino releases so I don't have to maintain an alternative Ethernet library on GitHub ;-)
The modified Ethernet library is attached as a zipped file.
 

Attachments

  • Ethernet118bonjour.zip
    74.3 KB · Views: 201
Last edited:
OK, Headroom wrote:

I guess my explanation was a little convoluted ;-) You don't want to have to configure the IP address on your Teesny every time you connect it to your computer. Lets see how I imagine for this to work:

1. You connect your device to the computer. I am not exactly sure how that is done. Based on your description you are not using Internet Sharing but "create a new Network" and then connect to that. I am not at my home computer right now but will try test either tonight or tomorrow how that works.

2. The Teensy requests an IP address from the computer per DHCP and the computer picks one from the pool of available adresses and assigns it to the Teensy.

3. The Teesny registers an _osc._udp service per Bonjour. This registration will also include a name "e.g. "etrumpet.local" to the IP address the Teensy received from the DHCP server. When this step is completed you can open the "ping" command in a terminal window on your mac and ping etrumpet.local instead of having to know the IP address of the Teensy. The service registration will also include on what port this service is registert and whether it is a UPD or TCP service.
Beeing able to resolve etrumpet.local into an actual IP address actually may already all you need to do as you are in full control of the UDP ports on the Teesny as well as on the MaxMSP side.

4. You start your Max MSP application which will browse the available services for _osc._udp and will be able to show available services you can then select from. There is a MaxMSP plugin available that will do this for you http://maxobjects.com/?v=objects&id_...=0&id_format=0
But, again as you are in full control of the port assignements you may not need the plugin.

That's it. The only "action you wuill have to perform is to connect the etrumpet-teesny to the computer. The rest is automatic!

I really would love to help you getting this to work. Your use case is a picturebook example of what can be done with OSC and Bonjour and you are using a very popular software in MaxMSP. I'd love to write an article of how to get this to work for my trippylighting.com blog.

I personally use OSC and Bonjour in a very similarly fashion to control my LED lighting systems. The Teensy in my LED system signs on to the router my home computes and iDevices connect to. Then it registers an OSC service per Bonjour, which in turn is picked up by TouchOSC on my iPhone or iPad and I can remotely controll my creations without having to configure an IP address or port or have to think about what protocol is in involved.

and I replied:

In answering

1. I have internet sharing on but probably I don't have to. Did not try without yet.

2. Yes. In my case that is always 192.168.2.4 so no worries there.

3. This is the step I don't understand.
The Teesny registers an _osc._udp service per Bonjour
. Is there any code involved or does this work automatically when including the ethernet library in my sketch?
Then the second step:
This registration will also include a name "e.g. "etrumpet.local" to the IP address the Teensy received from the DHCP server
. Where do I set this name? Is that in the software as well?
The rest is clear.

4. Ok. If I listen on the correct port and the teensy is connected to the local network and sends data to the IP address of that local network than I should see the data coming in in MAXMSP. The object for that is UDPreceive (formerly developed by CNMAT and now part of MAXMSP) which listens on the specified port address of the network that the computer is part of. (I am not totally clear where MAXMSP is listening exactly I must be honest)

Thanks for all your time again.

Best, Hans.
 
You will need a little extra code in your current sketch.
First, however, you need to download the EthernetBonjour library from
my GitHub repository

Then you need to replace the current Teensyduino Ethernet Library with the one I zipped in my last post in this thread.
It is fully backwards compatible with the current Ethernet library and with a little luck Paul will accept my changes and it will be integrated into one of the next Teensyduino releases 1.19 or 1.20.

The EthernetBonjour library contains several example sketches that you can play with. The ones you are interested in for your project register services. If these execute successfully you can see the advertised Service in the BonjourBrowser on the Mac.
 
Last edited:
Dear Headroom,

I got the ping working in the Discovering services example of your bonjour library but if I run the program on the teensy I am unsure what kind of Bonjour service name I have to supply. I tried all kinds of services from the IANA list but none worked. Although I solved my initial problem considering plug and play (see below) it would still be nice if you could point me in the right direction for bonjour.

Anyway as far as the solution for my problem goes, I have been stupid again. Of course the computer has its own ip number as well and I thought it would be something like 169.254.0.1 following the self assigned network addresses of both the ethernet and the Wi-Fi but that did not work. Of course I should have looked at the ip address that my teensy got assigned (192.168.2.4) which makes 192.168.2.1 quite obvious if you are more familiar with networks then me.... I even don't need a local network to get it to work.

Alas without the bonjour search I probably would not have found it so thanks again.

Best, Hans.
 
Being able to ping the teensy is a very important step and I am glad that this works! It is , however, a little unfortunate that you tried the Service Discovery. This does not work with the Teensy behind the little pocket router. I have not figured out yet why. If you use an ethernet cable and plug it directly into the WIZ820io and the Ethernet port on your mac you can discover al the services on your mac. However, for your application the service discovery on the Teensy is not needed anyway. What you want the Teensy to do is to register a service.

To see which Bonjour services are registered and basically as a little debugging tool I would recommend for you to download the Bonjour Browser from TildeSoft. Or you could use a little utility on your iPhone called Discovery.

To add a service - an _osc._udp service, this needs to go into the setup section of your sketch:

Code:
    if (EthernetBonjour.begin(etrumpet)){ //this is the Bonjour host name. It must be unique! If you have more than one Teensy registering services you need to either assign another name. You can ping this now as etrumpet.local
       Serial.println("Setting Bonjour Name successful");
    }
    else{
      Serial.println("Bonjour Name could not be set");
    }

  if(
		  EthernetBonjour.addServiceRecord("Teensy3_Frankie OSC Server._osc", //this is the service description you will see in the Bonjour Browser
				  serverPort,
				  MDNSServiceUDP)){
	  Serial.println("Bonjour Service Record added successfully");
  }
  else{
	  Serial.println("Bonjour Service could not be added");
  }
 
Last edited:
It compiles on Arduino.
Did anyone try to port this library for Intel Galileo?
It is using Arduino IDE 1.5.3. It seems their file structure is messed up. So I had to do the following

1. Add #include <EthernetUdp.h> in EthernetBonjor.h
2. Copy all the files (not directories) of Ethernet118bonjour directory to EthernetBonjour directory [Yes, putting Ethernet118bonjour directory in the library folder doesn't work!!]
3. Copy all the files from Ethernet118bonjour\utility directory to EthernetBonjour\utility directory

Then when I compile, I see below error. It is not working with the Ethernet chip they have. Unfortunately, I can't figure out what Ethernet chip Galileo has. Any suggestion?

---------------------------------------------------------

Arduino: 1.5.3 (Windows 7), Board: "Intel® Galileo"

In file included from C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\Dhcp.cpp:4:0:
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h: In static member function 'static void W5100Class::initSS()':
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h:325:36: error: 'DDRB' was not declared in this scope
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h:325:51: error: '_BV' was not declared in this scope
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h: In static member function 'static void W5100Class::setSS()':
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h:326:36: error: 'PORTB' was not declared in this scope
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h:326:51: error: '_BV' was not declared in this scope
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h: In static member function 'static void W5100Class::resetSS()':
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h:327:36: error: 'PORTB' was not declared in this scope
C:\Galileo\arduino-1.5.3\libraries\EthernetBonjourCommon\utility/w5100.h:327:51: error: '_BV' was not declared in this scope
 
I am assuming you got a copy of the library from
my GitHub repository ?

If so, I converted the library from its hardware dependence to use only UDP calls from the EthernetUDP library.
If the Arduino Galileo has an EthernetUDP.h and EthernetUDP.cpp that would be a good start. The normal Arduino EthernetUDP.h and EthernetUDP.cpp files include hardware dependent call directly to the Ethernet chip used on the Arduino Ethernet shield. I added one more function to these two files to allow for multicasting support. Details are in this thread. If there are Galileo specific EthernetUDP files then very likely these need similar modifications for the specific Ethernet hardware use on the Galileo. I don't own an Arduino Galileo and chances are slim to none that I'll ever buy one. I am quite happy with PJRC's Teensy boards.

While I do intend to continue answering this question as it may help also here on the Teensy forum, but I hope you do realize that this forum is aimed at PJRC products and not intended to address problems with other Arduino boards ;-)
 
Last edited:
I don't think anyone is suggesting to use the Arduino Galileo with an Ethernet shield. That'd be kinda silly ;-) However, to access the Ethernet functionality on this board you use the standard Ethernet library, which contains Galileo hardware specific code.

In order to get the Bonjour library working with the Galileo one would have to add a similar function as suggested HERE using the Galileo hardware. Provided it even supports mDNS
 
Status
Not open for further replies.
Back
Top