Arduino库教程-Bridge-Yun First Config
Yún First Configuration(yun的初次配置)
这个例子展示怎样用你的yun设备连接到一个WiFi网络(在整个过程将串口监视器作为通讯接口)。
上传程序到yun设备,并且打开串口监视器。串口监视器输出将会显示有效的WiFi网络,然后询问选择使用哪个。你必须输入网络的密码,然后要求为yun设备起个名字和密码。如果与被选择的网络成功连接,你获得一个确定信息和设计到yun设备的IP。通过粘贴IP地址到网页浏览器,你可以得到yun平台的更多选项。
如果有些东西出错,你可以重新开始这个流程;如果你想要连接的网络不在列表上,你可以继续人工选择特定的网络SSID和passkey。
注意:这个程序要求yun设备运行在1.6.2或者更新的版本。请检查更新教程,确保你运行的是最新有效版本。
硬件要求
- Yún 开发板或者 shield
- 一个连接到互联网的无线网络
电路
这个例子不需要额外的连线
图由 Fritzing 软件绘制
软件要求
- 库
Process.h被用来进入在linux processor的processes,和其他,如shell脚本。这里我们用它来获得APs的列表和执行其他动作来使我们知道WiFi的参数。
- 函数
String getUserInput(String out, bool obfuscated) - 通过串口监视器管理从用户那里的输入,打印回到窗口。当密码被输入时,boolean类型的变量“obfuscated”被用来打印 “*” 。
void wifiConfig(String yunName, String yunPsw, String wifissid, String wifipsw, String wifiAPname, String countryCode, String encryption) - 用Process来执行一系列的linux下的命令和脚本,那些按用户选择设置WiFi和网络参数。
void startSerialTerminal() – 简单初始化两个需要的串口接口来执行程序要求的动作。
void loopSerialTerminal() – 创建两个串口接口的连接,一个通过USB和PC交谈,另一个和Linux Processor交谈。它有一个命令模式(引用类型'~' ),关闭Birgde和允许通过其他芯片设置不同的通讯速度
- 用法
这个程序用IDE的串口监视器来和你互动,询问和配置关联的信息。yun设备用pin0和pin1上的硬件串口接口来和开发板通讯,因而这个程序要求第二种合适的硬件串口接口来工作。请准备好SSID(可接入点名字)和进入WiFi网络的钥匙或者密码。载入这个程序,然后打开串口监视器,点击在图标栏的右边的放大镜图标。你将会看到一个信息如下面屏幕显示。
在shield上的蓝色LED灯将会在一会儿后开始闪烁;当扫描过程完成,程序将会在一个有限的列表里提供所有有效的APs。要求扫描网络的时间取决于APs的数目和它们的信号强度。你选择要用的AP,输入在输入列表对应的序号。请记得在串口监视器里使能“NL”作为行的结尾。
AP的选择触发连接过程,并且Yún设备会感应网络是开放的还是受保护的。在之后的情况下,你会被要求提供钥匙。Yún设备需要命名和受密码保护,来允许简单和安全的连接。遵循这些步骤,你的设备可以连接到WiFi网络,关闭AP模式和启动选定的WiFi网络接入。在这个过程的最后,程序会显示从WiFi的DHCP服务器获得IP地址。
如果连接失败,程序会报告,并且建议用yun设备的重置来重新启动整个程序。
样例代码
- 完整程序如下:
/*
Arduino Yún First configuration sketch
Configures the Yún101/YunShield/Yún WiFi and infos via the Bridge
Works correctly if Line Ending is set as "NewLine"
If your board has two USB ports, use the Native one
The circuit:
Arduino Yún/Yún101/YunShield with firmware > 1.6.1
created March 2016
by Arduino LLC
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/YunFirstConfig
*/
#include <Process.h>
#define MAX_WIFI_LIST 10
String networks[MAX_WIFI_LIST];
String yunName;
String yunPassword;
void setup() {
SERIAL_PORT_USBVIRTUAL.begin(9600); // initialize serial communication
while (!SERIAL_PORT_USBVIRTUAL); // do nothing until the serial monitor is opened
SERIAL_PORT_USBVIRTUAL.println(F("Hi! Nice to see you!"));
SERIAL_PORT_USBVIRTUAL.println(F("I'm your Yun101 assistant sketch"));
SERIAL_PORT_USBVIRTUAL.println(F("I'll help you configuring your Yun in a matter of minutes"));
SERIAL_PORT_USBVIRTUAL.println(F("Let's start by communicating with the Linux processor"));
SERIAL_PORT_USBVIRTUAL.println(F("When LED (L13) will light up we'll be ready to go!"));
SERIAL_PORT_USBVIRTUAL.println(F("Waiting..."));
SERIAL_PORT_USBVIRTUAL.println(F("(in the meanwhile, if you are using the IDE's serial monitor, make sure that it's configured to send a \"Newline\")\n"));
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin(); // make contact with the linux processor
digitalWrite(13, HIGH); // Led on pin 13 turns on when the bridge is ready
// Recover if the board is in AP mode - unused
Process wifiList;
bool master = false;
wifiList.runShellCommand(F("iwinfo | grep \"Mode: Master\""));
while (wifiList.available() > 0) {
wifiList.read();
master = true;
}
// Get the list of reachable networks
wifiList.runShellCommand(F("iwinfo wlan0 scan | grep ESSID | cut -d\"\\\"\" -f2"));
uint8_t num_networks = 0;
uint8_t i = 0;
char c;
bool dropNet = false;
networks[0].reserve(32);
while (wifiList.available() > 0) {
c = wifiList.read();
if (c != '\n') {
networks[i] += c;
} else {
// check if we already found networks[i] and eventually drop it
for (uint8_t s = 0; s < i; s++) {
if (networks[i].equals(networks[s])) {
dropNet = true;
}
}
if (i <= MAX_WIFI_LIST && dropNet == false) {
networks[i++].reserve(32);
} else {
dropNet = false;
networks[i]="";
}
}
}
num_networks = i;
String encryption;
String password;
int chose = 0;
// If networks number is 0, start manual configuration
if (num_networks == 0) {
SERIAL_PORT_USBVIRTUAL.println(F("Oops, it seems that you have no WiFi network available"));
SERIAL_PORT_USBVIRTUAL.println(F("Let's configure it manually"));
SERIAL_PORT_USBVIRTUAL.println(F("SSID of the network you want to connect to: "));
networks[0] = getUserInput(networks[0], false);
SERIAL_PORT_USBVIRTUAL.println(F("Password for the network you want to connect to: "));
password = getUserInput(password, true);
SERIAL_PORT_USBVIRTUAL.print(F("Encryption (eg WPA, WPA2, WEP): "));
encryption = getUserInput(encryption, false);
} else {
// else print them prepending a number
SERIAL_PORT_USBVIRTUAL.print(F("It looks like you have "));
SERIAL_PORT_USBVIRTUAL.print(num_networks);
SERIAL_PORT_USBVIRTUAL.println(F(" networks around you "));
SERIAL_PORT_USBVIRTUAL.println(F("Which one do you want to connect to?\n"));
for (i = 0; i < num_networks && i < MAX_WIFI_LIST; i++) {
SERIAL_PORT_USBVIRTUAL.print(i);
SERIAL_PORT_USBVIRTUAL.println(") " + networks[i]);
}
String selection;
selection = getUserInput(selection, false);
chose = atoi(selection.c_str());
}
// Extract the selected network security
bool openNet = false;
wifiList.runShellCommand("iwinfo wlan0 scan | grep \"" + networks[chose] + "\" -A5 | grep Encryption | cut -f2 -d\":\"");
while (wifiList.available() > 0) {
c = wifiList.read();
encryption += c;
}
if (encryption.indexOf("none") >= 0) {
openNet = true;
encryption = "none";
}
if (encryption.indexOf("WPA2") >= 0) {
encryption = "psk2";
}
if (encryption.indexOf("WPA") >= 0) {
encryption = "psk";
}
if (encryption.indexOf("WEP") >= 0) {
encryption = "wep";
}
if (openNet == false && password.length() == 0) {
SERIAL_PORT_USBVIRTUAL.print(F("It looks like you need a password to connect to "));
SERIAL_PORT_USBVIRTUAL.println(networks[chose]);
SERIAL_PORT_USBVIRTUAL.print(F("Write it here: "));
password = getUserInput(password, true);
}
// Change hostname/root password
SERIAL_PORT_USBVIRTUAL.println(F("We are almost done! Give a name and a password to your Yun"));
SERIAL_PORT_USBVIRTUAL.print(F("Name: "));
yunName = getUserInput(yunName, false);
SERIAL_PORT_USBVIRTUAL.print(F("Password: "));
yunPassword = getUserInput(yunPassword, true);
// Select a country code
String countryCode;
SERIAL_PORT_USBVIRTUAL.println(F("One last question: where do you live?"));
SERIAL_PORT_USBVIRTUAL.print(F("Insert a two letters county code (eg IT, US, DE): "));
countryCode = getUserInput(countryCode, false);
yunName.trim();
yunPassword.trim();
networks[chose].trim();
password.trim();
countryCode.trim();
// Configure the Yun with user provided strings
wifiConfig(yunName, yunPassword, networks[chose], password, "YUN" + yunName + "AP", countryCode, encryption);
SERIAL_PORT_USBVIRTUAL.print(F("Waiting for the Yun to connect to the network"));
}
bool Connected = false;
bool serialTerminalMode = false;
int runs = 0;
void loop() {
if (!serialTerminalMode) {
String resultStr = "";
if (!Connected) {
SERIAL_PORT_USBVIRTUAL.print(".");
runs++;
}
// If it takes more than 20 seconds to connect, stop trying
if (runs > 20) {
SERIAL_PORT_USBVIRTUAL.println("");
SERIAL_PORT_USBVIRTUAL.println(F("We couldn't connect to the network."));
SERIAL_PORT_USBVIRTUAL.println(F("Restart the board if you want to execute the wizard again"));
resultStr = getUserInput(resultStr, false);
}
// Check if we have an IP address
Process wifiCheck;
wifiCheck.runShellCommand(F("/usr/bin/pretty-wifi-info.lua | grep \"IP address\" | cut -f2 -d\":\" | cut -f1 -d\"/\"" )); // command you want to run
while (wifiCheck.available() > 0) {
char c = wifiCheck.read();
resultStr += c;
}
delay(1000);
if (resultStr != "") {
// We got an IP, freeze the loop, display the value and "spawn" a serial terminal
Connected = true;
resultStr.trim();
SERIAL_PORT_USBVIRTUAL.println("");
SERIAL_PORT_USBVIRTUAL.print(F("\nGreat! You can now reach your Yun from a browser typing http://"));
SERIAL_PORT_USBVIRTUAL.println(resultStr);
SERIAL_PORT_USBVIRTUAL.print(F("Press 'Enter' key twice to start a serial terminal"));
resultStr = getUserInput(resultStr, false);
serialTerminalMode = true;
//startSerialTerminal();
SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command
delay(100);
SERIAL_PORT_HARDWARE.println("\nreset\n\n");
SERIAL_PORT_HARDWARE.flush();
SERIAL_PORT_HARDWARE.println("\nreset\n\n");
SERIAL_PORT_HARDWARE.write((uint8_t *)"\n", 1);
}
} else {
loopSerialTerminal();
}
}
String getUserInput(String out, bool obfuscated) {
/*
while (SerialUSB.available() <= 0) {}
while (SerialUSB.available() > 0) {
char c = SerialUSB.read();
out += c;
}
return out;
*/
while (SERIAL_PORT_USBVIRTUAL.available() <= 0) {}
while (1) {
char c = SERIAL_PORT_USBVIRTUAL.read();
if (c == '\n' || c == '\r')
break;
else {
if (c != -1) {
out += c;
if (obfuscated)
SERIAL_PORT_USBVIRTUAL.print("*");
else
SERIAL_PORT_USBVIRTUAL.print(c);
}
}
}
SERIAL_PORT_USBVIRTUAL.println("");
return out;
}
void wifiConfig(String yunName, String yunPsw, String wifissid, String wifipsw, String wifiAPname, String countryCode, String encryption) {
Process p;
p.runShellCommand("blink-start 100"); //start the blue blink
p.runShellCommand("hostname " + yunName); //change the current hostname
p.runShellCommand("uci set system.@system[0].hostname='" + yunName + "'"); //change teh hostname in uci
p.runShellCommand("uci set arduino.@arduino[0].access_point_wifi_name='" + wifiAPname + "'");
//this block resets the wifi psw
p.runShellCommand("uci set wireless.@wifi-iface[0].encryption='" + encryption + "'");
p.runShellCommand("uci set wireless.@wifi-iface[0].mode='sta'\n");
p.runShellCommand("uci set wireless.@wifi-iface[0].ssid='" + wifissid + "'");
p.runShellCommand("uci set wireless.@wifi-iface[0].key='" + wifipsw + "'");
p.runShellCommand("uci set wireless.radio0.channel='auto'");
p.runShellCommand("uci set wireless.radio0.country='" + countryCode + "'");
p.runShellCommand("uci delete network.lan.ipaddr");
p.runShellCommand("uci delete network.lan.netmask");
p.runShellCommand("uci set network.lan.proto='dhcp'");
p.runShellCommand("echo -e \"" + yunPsw + "\n" + yunPsw + "\" | passwd root"); //change the passwors
p.runShellCommand("uci commit"); //save the mods done via UCI
p.runShellCommand("blink-stop"); //start the blue blink
p.runShellCommand("wifi ");
}
long linuxBaud = 250000;
void startSerialTerminal() {
SERIAL_PORT_USBVIRTUAL.begin(115200); // open serial connection via USB-Serial
SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux
}
boolean commandMode = false;
void loopSerialTerminal() {
// copy from USB-CDC to UART
int c = SERIAL_PORT_USBVIRTUAL.read(); // read from USB-CDC
if (c != -1) { // got anything?
if (commandMode == false) { // if we aren't in command mode...
if (c == '~') { // Tilde '~' key pressed?
commandMode = true; // enter in command mode
} else {
SERIAL_PORT_HARDWARE.write(c); // otherwise write char to UART
}
} else { // if we are in command mode...
if (c == '0') { // '0' key pressed?
SERIAL_PORT_HARDWARE.begin(57600); // set speed to 57600
SERIAL_PORT_USBVIRTUAL.println("Speed set to 57600");
} else if (c == '1') { // '1' key pressed?
SERIAL_PORT_HARDWARE.begin(115200); // set speed to 115200
SERIAL_PORT_USBVIRTUAL.println("Speed set to 115200");
} else if (c == '2') { // '2' key pressed?
SERIAL_PORT_HARDWARE.begin(250000); // set speed to 250000
SERIAL_PORT_USBVIRTUAL.println("Speed set to 250000");
} else if (c == '3') { // '3' key pressed?
SERIAL_PORT_HARDWARE.begin(500000); // set speed to 500000
SERIAL_PORT_USBVIRTUAL.println("Speed set to 500000");
} else if (c == '~') { // '~` key pressed?
SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command
SERIAL_PORT_USBVIRTUAL.println("Sending bridge's shutdown command");
} else { // any other key pressed?
SERIAL_PORT_HARDWARE.write('~'); // write '~' to UART
SERIAL_PORT_HARDWARE.write(c); // write char to UART
}
commandMode = false; // in all cases exit from command mode
}
}
// copy from UART to USB-CDC
c = SERIAL_PORT_HARDWARE.read(); // read from UART
if (c != -1) { // got anything?
SERIAL_PORT_USBVIRTUAL.write(c); // write to USB-CDC
}
}
[Get Code]
更多
- Bridge: 从网页浏览器进入开发板的引脚。
- Console ASCII Table: 示范了怎样打印多种格式到控制台。
- Console Pixel: 通过控制台控制一个LED灯。
- Console Read: 从控制台那里分析信息,然后重复发送返回。
- Datalogger: 在SD卡上保存传感器信息。
- File Write Script: 示范怎样在Process上写入和执行外壳脚本。
- HTTP Client: 建造一个简单的客户端,可以下载网页并且打印到串口监视器。
- HTTP Client Console: 建造一个简单的客户端,可以下载网页并且用控制台通过WIFI打印到串口监视器。
- Mailbox Read Messages: 用REST API通过一个网页发送文本信息到。
- Process: 示范怎么用Process运行 Linux 命令。
- Remote Due Blink: 示范怎么远程上传程序到DUE开发板上。
- Shell Commands: 用Process 来运行 shell 命令。
- SpacebrewYun: 在Arduino IDE软件的例子上看更多关于 Spacebrew 文档信息。
- Temboo: 在Arduino IDE软件的例子上看更多关于 Temboo 文档信息。
- Temperature Web Panel: 当浏览者要求时,粘贴传感数据到网页上。
- Time Check: 从网络的时间服务器获得时间,并且打印到串口监视器。
- WiFi Status: 运行一个预配置的脚本,报告返回当前wifi网络的强度。
- Yun First Config: 用串口监视器不费力地连接你的云产品到wifi网络,并且在上面回答一些简单的问题。
- Yun Serial Terminal: 通过串口监视器进入Linux终端。
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号