Bonjour/Zeroconf with Arduino
转自:http://gkaindl.com/software/arduino-ethernet/bonjour
Bonjour/Zeroconf with Arduino
Bonjour/Zeroconf with Arduino
A small implementation of Bonjour/Zeroconf (Wikipedia)
that can run on your ethernet-equipped Arduino board! It implements both MDNS (multicast DNS) and DNS-SD (DNS Service Discovery), so that you can register services from your Arduino, but also discover services registered by other nodes on the network.
As examples, you can use this library to register a small web-server running on your Arduino, which can then be easily discovered by other users on your network. Or use it to discover nodes offering a service your Arduino sketch can work with. It's just like
Bonjour running on your desktop.
Documentation
The library ships with 4 extensively commented examples, but here's an additional run-down of the public methods. Nevertheless, I suggest to have a look at the examples for a short introduction to the library.
int begin();
int begin(const char* bonjourName);
In order to initialize the library, you must call begin() before any other library method, but after your Ethernet shield itself has been initialized, preferably within your setup() function. When you initialize the library, you can supply
an (arbitrary) name under which your Arduino board can then be referenced on the network.
The default name is "arduino", which means that you can access the board conveniently on the Bonjour network via the MDNS name "arduino.local" — However, do not attach the ".local" postfix when you specify the name in begin().
The method will return a non-zero result if the library could be initialized successfully, otherwise 0 will be returned.
void run();
You should call run() at least once per loop() iteration. This gives the Bonjour module a chance to fulfill your requests and to interact with the Bonjour network.
If you fail to call run() periodically, the Bonjour library will not work at all.
int setBonjourName(const char* bonjourName);
You can use this method to change the Bonjour name of your Arduino board at any time after setting the initial name via begin(). Changing the Bonjour name after you have already registered services might cause some clients to fail to connect properly for a
short time, until the name change has propagated.
Do not include the ".local" postfix when you specify a new Bonjour name!
This method returns a non-zero value on success and 0 if there was an internal (memory) error.
int addServiceRecord(const char* name,
uint16_t port,
MDNSServiceProtocol_t proto);
int addServiceRecord(const char* name,
uint16_t port,
MDNSServiceProtocol_t proto,
const char* textContent);
The addServiceRecord() methods enable you to register a service running on your Arduino board with the Bonjour network, so that it can be discovered by other Bonjour peers. The difference between them only is that the second version takes an
additional text content argument, whereas the first one does not.
The first argument is the name of your service. Typically, this is an instance name and a service name, separated by a dot. The service name needs to be additionally prefixed with an underscore. An incredibly extensive list of defined service names is available here.
Examples of a valid name-argument would be "My Arduino Web Server._http" or "My Arduino iChat client._presence".
The second argument specifies the port on which the service is listening on your Arduino board. As an example, webservers are typically listening on port 80. You need to make sure that you actually are listening for network traffic on the port!
The third argument is the TCP/UDP-layer protocol your service is running on. Specify MDNSServiceTCP for TCP-based services or MDNSServiceUDP for UDP-based services.
The "textContent" argument lets you specify a TXT record to be associated with your service. TXT records are typically used to contain additional information about a service, such as the initial path on the server in case of a HTTP endpoint. A good list of
defined TXT keys for many services can be found here,
and the DNS-SD TXT record format in general is described here.
Specify the TXT record as a zero-terminated string.
The method will return a non-zero value upon success and zero otherwise (for example, when memory is exhausted).
void removeServiceRecord(uint16_t port,
MDNSServiceProtocol_t proto);
void removeServiceRecord(const char* name,
uint16_t port,
MDNSServiceProtocol_t proto);
Call removeServiceRecord() to remove unregister a service from the Bonjour network. The arguments should match those given to a previous addServiceRecord() call. The service identified by the arguments will be removed, and an announcement of
the removal will be distrubted to Bonjour peers immediately.
The method returns a non-zero value on success and 0 on failure.
void removeAllServiceRecords();
You can use removeAllServiceRecords(); to remove all previously added service registrations at once, so that your Arduino board does not vend services anymore.
void setNameResolvedCallback(BonjourNameFoundCallback newCallback);
Use setNameResolvedCallback() to specify a callback function of your own, which will be called when you resolve a host name over Bonjour.
The argument must be a pointer to a function which takes two arguments (in this order): A "const char*" and a "const byte[4]": The former will hold the host name that you wanted resolved, the latter will hold the IP address of the host (4 bytes) if it could
be resolved, or NULL if no Bonjour peer responded to the query.
Be sure to have a callback set before you attempt to resolve a host name with resolveName()!
int resolveName(const char* name,
unsigned long timeout);
Provided that you have already specified a callback, you can use resolveName() to find the IP address of a Bonjour host. The first argument is the host's Bonjour name (again, without the ".local" postfix), the second argument is a timeout (in
milliseconds) that you want the query to run for before it times out, calling the callback with a NULL IP address argument.
While a query is running, the Bonjour library will resend the query every second, until your timeout is reached or a response has been obtained.
If you want to run a query indefinitely (for example, to wait for a host with a given Bonjour name to join the network), you can specify zero (0) as the timeout argument to disable the timeout mechanism.
resolveName() will return a non-zero value on success or 0 on failure. Only one name query can run at any given time: Calling resolveName() again before the current query is finished will cause the current query to be overwritten by the new one.
void cancelResolveName();
If you want to stop a currently running name query, call cancelResolveName() to cancel it immediately. Your callback function will not be called in this case.
int isResolvingName()
Use isResolvingName() to find out whether the library is currently busy resolving a host name. If so, this method will return a non-zero value, otherwise it will return zero.
void setServiceFoundCallback(BonjourServiceFoundCallback newCallback);
setServiceFoundCallback() is used to specify a callback that is called when a service is discovered. You need to specify a callback of your own before you can discover services.
The argument is a pointer to a function that takes the following arguments (in this order): A "const char*", an "MDNSServiceProtocol", another "const char*", a "const byte[4]", an "unsigned short" and one more "const char*": They will be filled with the service
type (such as "_http"), the transport protocol (MDNSServiceTCP or MDNSServiceUDP), the service name (such as "My Arduino Web Server"), the service endpoint's IP address (4 bytes), the endpoint's port number and (if available) the service record's TXT contents
(zero-terminated), NULL otherwise.
When your service discovery timeout is reached, your callback will be called one more time, but all arguments (except the service type and protocol) will be NULL.
If you do not specify a callback, you cannot discover any services.
int startDiscoveringService(const char* serviceName,
MDNSServiceProtocol_t proto,
unsigned long timeout);
startDiscoveringService() causes the Bonjour library to query the network for services of a particular type, provided that you have specified an appropriate callback.
The first argument denotes the service type, prefixed by an underscore (such as "_http"). For a comprehensive list of service types, have a look here.
The second argument is the desired transport protocol (either MDNSServiceTCP or MDNSServiceUDP, for TCP or UDP, respectively).
The third argument is the timeout (or total duration) of the search in milliseconds. The Bonjour library will keep waiting for replies until this timeout is reached, when it will call the callback again, but with a NULL argument as service name and IP address,
so that you know that the discovery time has elapsed.
Note that the Bonjour library will resend the discovery request every 10 seconds: Thus, if you specify more than 10 seconds (10000 milliseconds) as timeout argument, you will receive duplicate results as well, so be prepared.
You can specify a timeout value of zero (0) to let the discovery process run indefinitely.
You can only discover a single service type concurrently, so subsequent calls of this method while another discovery is running will overwrite the old discovery request.
void stopDiscoveringService();
Call the stopDiscoveringService() method to immediately stop discovering services. In this case, your callback will not be called.
int isDiscoveringService();
Use the isDiscoveringService() method to find out if a service discovery is currently running: If so, a non-zero value will be returned. Otherwise, zero is returned.
Notes a.k.a. "Things you should know"
- Registering services is very reliable, but discovering services is not (due to the complexity of the process): If it is necessary for your application, you might want to run the discovery process more than once. Generally,
it works rather well, though! - Due to memory limitations, you can only discover a maximum of 6 service endpoints per host and service type. For example, if a host vends 10 HTTP endpoints, only the first 6 will be found. If you want to risk memory exhaustion/corruption,
you can change the MDNS_MAX_SERVICES_PER_PACKET macro in EthernetBonjour.cpp. - Also due to similar memory limitations, you can only vend up to 8 services running on your board. If you want to change this limitation, edit "NumMDNSServiceRecords" in EthernetBonjour.h (but note that the WIZnet chipset
on the ethernet shield only supports 4 sockets anyway, one already taken up by the Bonjour library, so 8 services might be way too much anyway. Thus, you could also lower this constant to free up some memory). - The library is rather large (about 14K) and will thus only fit onto Arduino boards with at least 32K of flash memory (such as the Duemilanove, the Nano 3.0 or the MEGA). You might be able to fit it onto older boards by getting
rid of the discovery stuff if you're only interested in registering services, for example. Personally, I've developed the library on a Duemilanove and use it on MEGA boards. - The library has only been tested with Apple's Bonjour (on both a small and rather large network): Service registration will most likely work with other implementations as well, service discovery might not — Give
it a try and email me patches! - The implementation adheres to the Zeroconf specs, but is rather "noisy" in that service registration is resent with a Time-To-Live of 2 minutes — This is because I do not want stale registrations to hang around for long when
you reset your board, and a modern network should really be able to handle the additional couple of bytes every two minutes ;-)
Pro Tip: Save code size if you don't need all features
Bonjour/ZeroConf is a complex protocol, so the full library is quite large and can eat up a lot of flash space on your Arduino. However, if all you want is giving your Arduino board a Bonjour name like arduino.local, so that you don't need to remember
any IP addresses (or get them dynamically via DHCP), you can disable some advanced features at compile time for massive size savings (up to 7K).
If you open the file EthernetBonjour.cpp within the library, you'll notice two macros defined right at the top: HAS_SERVICE_REGISTRATION andHAS_NAME_BROWSING. They are set to enabled per default. The first
one governs some code necessary only if you want to register link-local Bonjour service endpoints. You can turn this off if you don't need it (saves about 1.5K). The latter controls name and service browsing: If you don't want to send any queries to link-local
Bonjour, turn this off to save about 5.5K of code size. Service registration depends on name browsing, so you can either turn off just the former, or both, but not just the latter. If you turn off the features, but use them anyway, the resulting code will
simply time out at all times.
Again, the main focus for these (and the only thing I have tested) is to turn everything off except host name advertising, so that you can, as an example, have a sensor platform run at the Bonjour address MySensorPlatform.local for convenience, but
don't need any other Bonjour features.
Bonjour/Zeroconf with Arduino的更多相关文章
- 【读书笔记】iOS网络-使用Bonjour实现自组织网络
Bonjour就是这样一种技术:设备可以通过它轻松探测并连接到相同网络中的其他设备,整个过程只需要很少的用户参与或是根本就不需要用户参与.该框架提供了众多适合于移动的使用场景,如基于网络的游戏,设备间 ...
- 【读书笔记】iOS-网络-使用Bonjour实现自组织网络
Bonjour就是这样一种技术:设备可以通过它轻松探测并连接到相同网络中的其他设备,整个过程只需要很少的用户参与或是根本就不需要用户参与.该框架提供了众多适合于移动的使用场景,如基于网络的游戏,设备间 ...
- 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino
大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...
- nodejs操作arduino入门(javascript操作底层硬件)
用Javascript来操作硬件早就不是一件稀奇的事情了. 所以作为一名电子专业出身的FE,我也打算尝试一下用js来驱动arduino: 要想操作这些底层硬件,肯定是需要一些工具的,我这里介绍的工具主 ...
- 了解 ARDUINO 101* 平台
原文链接 简介 作为一名物联网 (IoT) 开发人员,您需要根据项目的不同需求,选择最适合的平台来构建应用. 了解不同平台的功能至关重要. 本文第一部分比较了 Arduino 101 平台和 Ardu ...
- 在web浏览器上显示室内温度(nodeJs+arduino+socket.io)
上次的nodejs操作arduino入门篇中实现了如何连接arduino.这次我们来实现通过arduino测量室内温度并在浏览器上显示出来. [所需材料] 硬件:LM35温度传感器,arduino u ...
- 初探物联网 - 基于Arduino的气象站和View and Data API的结合实例
如果你参加了上个月在北京的Autodesk 开发者日,你应该看到了我做的关于Arduino的物联网实例演示,如果你没看到,欢迎参加14号在上海的开发者日,到时候我会再演(xian)示(bai)一下. ...
- Arduino 1602液晶屏实验和程序
在Arduino IDE中, 项目->加载库->管理库中搜索LiquidCrystal,然后安装即可 1.接线图 2.引脚图 3.最简单程序 #include <LiquidCrys ...
- Arduino uno 教程~持续更新~
http://arduino.osall.com/index.html http://study.163.com/search.htm?t=2&p=Arduino http://www.ard ...
随机推荐
- mongodb--group聚合运算
mongodb本质就是要做一个高性能,能简单则简单,不要把mongodb中的运算做的太复杂 count 最简单的一个聚合方法 distinct 选择结果中剔除重复的一个键值, 跟sql语句的效果是一样 ...
- PAT Perfect Sequence (25)
题目描写叙述 Given a sequence of positive integers and another positive integer p. The sequence is said to ...
- 通过UrlRewriter配置MVC4伪静态
有些项目须要设置静态.这样能够被站点收录了,提高站点的排名.内容. 假设地址后面有www.a.com/xx.html?id=1是不行,还是不能达到一些需求.怎么才干实现www.a.com/1/xx.h ...
- 125条常见的java面试、笔试题大汇总
1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解所有问题,而仅仅是选择当中的一部分,临时不用部分细节.抽象包含两个方面,一是过程抽象. ...
- jmeter函数和变量
函数和变量广泛的应用在JMeter的传参过程,其中函数可以被认为是某种特殊的变量,它们可以被采样器或者其他测试元件所引用. 常用函数 1.__RamdomString() / __Ramdom() 获 ...
- SVNserver搭建和使用(二)
上一篇介绍了VisualSVN Server和TortoiseSVN的下载,安装,汉化.这篇介绍一下怎样使用VisualSVN Server建立版本号库,以及TortoiseSVN的使用. 首先打开V ...
- bzoj1081: [SCOI2005]超级格雷码(dfs)
1081: [SCOI2005]超级格雷码 题目:传送门 题解: 又是一道水题... 因为之前做过所以知道规律: 如n=2 B=3: 00 10 20 21 11 01 02 12 22 ...
- The Unique MST--hdoj
The Unique MST Time Limit : 2000/1000ms (Java/Other) Memory Limit : 20000/10000K (Java/Other) Tota ...
- Sybase 动态改变存储过程里查询的数据库
declare @sql varchar(500) select @sql='select * from '+@dbName+'..tableName' --此句用于执行拼接好的SQL语句 exec( ...
- redis启动加载过程、数据持久化
背景 公司一年的部分业务数据放在redis服务器上,但数据量比较大,单纯的string类型数据一年就将近32G,而且是经过压缩后的. 所以我在想能否通过获取string数据的时间改为保存list数据类 ...