我创建了一个PHP脚本,因此我可以从我的在线数据库(MySQL)中检索数据,但是我无法将该信息传递给我的arduino + Ethernet Shield(使用Ethercard.h)。
我想要的是将我的PHP脚本作为字符串向量重新获得。
我的PHP脚本返回的示例:
ABCDF
GHYEJ
JDYDI
HSTSU
PIFYF
我希望它能在我的Arduino中成为现实:
char* test = {"ABCDF", "GHYEJ". "JDYDI", "HSTSU", "PIFYF" };
任何人都可以帮我这个吗?
编辑: 所以,我正在尝试@ frarugi87解决方案,但我的DNS失败了。以下是我使用的代码:
#include <enc28j60.h>
#include <EtherCard.h>
#include <net.h>
#define HTTP_HEADER_OFFSET 0
/* Setup for Ethernet Library */
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
static byte myip[] = {192,168,1,58};
static byte gatewayip[] = {192,168,1,1};
static byte dnsip[] = {8,8,8,8}; //Google DNS
const char website[] PROGMEM = "http://arksecurity.net16.net";
byte Ethernet::buffer[700];
static uint32_t timer = 0;
static void response_callback (byte status, word off, word len){
Serial.print((const char*) Ethernet::buffer + off + HTTP_HEADER_OFFSET);
}
void setup() {
Serial.begin(57600);
if (ether.begin(sizeof Ethernet::buffer, mymac, 8) == 0)
Serial.println("Failed to access Ethernet controller");
else
Serial.println("Ethernet controller initialized");
ether.staticSetup(myip, gatewayip, dnsip);
if(!ether.dnsLookup(website)){
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
}
void loop() {
word pos = ether.packetLoop(ether.packetReceive());
if (millis() > timer){
timer = millis() + 5000;
ether.browseUrl("/", "test.php", website, response_callback);
}
}
我在这里做错了吗?
Edit2:好吧,我让它运行了。 DNS问题是由我的路由器引起的,所以我不得不将其设置为192.168.1.1并且我还必须对ether.browseUrl进行一些调整,因为它也返回错误。 这就是我现在的代码:
#include <enc28j60.h>
#include <EtherCard.h>
#include <net.h>
#define HTTP_HEADER_OFFSET 50
/* Setup for Ethernet Library */
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
static byte myip[] = {192,168,1,58};
static byte gatewayip[] = {192,168,1,1};
static byte dnsip[] = {192,168,1,1}; //Google DNS
const char website[] PROGMEM = "www.arksecurity.net16.net";
byte Ethernet::buffer[700];
static uint32_t timer = 0;
static void response_callback (byte status, word off, word len){
Serial.print((const char*) Ethernet::buffer + off + HTTP_HEADER_OFFSET);
}
void setup() {
Serial.begin(57600);
if (ether.begin(sizeof Ethernet::buffer, mymac, 8) == 0)
Serial.println("Failed to access Ethernet controller");
else
Serial.println("Ethernet controller initialized");
ether.staticSetup(myip, gatewayip, dnsip);
if(!ether.dnsLookup(website)){
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
}
void loop() {
word pos = ether.packetLoop(ether.packetReceive());
if (millis() > timer){
timer = millis() + 5000;
ether.browseUrl(PSTR("/test."),"php", website, response_callback);
}
}
现在我必须将我得到的数据保存到char * []中。有什么想法吗?
EDIT3:
所以这就是我的代码到目前为止的样子。问题是,在最后的比较中我做了#34; for(int i = 0; i&lt; 20 - 1; i ++)&#34;我得到所有&#34;错误&#34;就像前两个响应回拨一样,之后就开始得到一个&#34; OK&#34;喜欢它。是预期的吗?
之后,我想让它每天只调用一次response_callback,就像在午夜一样。有可能吗?
#define HTTP_HEADER_OFFSET 163
#define MAX_STRINGS 20
#define MAX_STRING_LENGTH 8
#define REQUEST_EVERY_X_MS 5000
/* Setup for Ethernet Library */
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
const char website[] PROGMEM = "www.arksecurity.net16.net";
const char device[] = "0001";
char test[MAX_STRINGS][MAX_STRING_LENGTH+1];
String test2 = "1234";
char * comp[20];
uint8_t receivedResponse;
unsigned long timer;
byte Ethernet::buffer[700];
static void response_callback (byte status, word off, word len) {
int i_string = 0;
int i_char = 0;
int i_ethBuff = off + HTTP_HEADER_OFFSET;
char carat;
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat =(char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
if (carat == '\n')
{ // New line char = new string
if (i_string < MAX_STRINGS - 1){
i_string++;
i_char = 0;
}
else
break;
}
else
{
if (i_char < MAX_STRING_LENGTH)
{
test[i_string][i_char] = carat;
i_char++;
} // otherwise discard the char (max length of string reached)
}
}
receivedResponse = 1;
}
void setup() {
if (ether.begin(sizeof Ethernet::buffer, mymac, 8) == 0)
{
Serial.println("Failed to access Ethernet controller");
while(1);
}
else
Serial.println("Ethernet controller initialized");
Serial.println();
if (!ether.dhcpSetup())
{
Serial.println("Failed to get configuration from DHCP");
while(1);
}
else
Serial.println("DHCP configuration done");
if (!ether.dnsLookup(website))
{
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
timer = millis() - REQUEST_EVERY_X_MS;
}
void loop() {
word pos = ether.packetLoop(ether.packetReceive());
if (millis() - timer > REQUEST_EVERY_X_MS){
timer += REQUEST_EVERY_X_MS;
receivedResponse = 0;
ether.browseUrl(PSTR("/DevicesQuery.php?device="),device , website, response_callback);
while (!receivedResponse);
for(int i=0; i < 20 - 1; i++){
comp[i] = test[i];
if(test2.equals(comp[i])){
Serial.println("OK");
}
else
Serial.println("Wrong");
}
}
}
Edit4:使用另一种比较。我希望它每5秒捕获一次数据,直到他收到任何东西并让它等待很长时间。问题是,当我使timer2 = 500000;它实际上使它更快地捕获数据。那是为什么?
#include <enc28j60.h>
#include <EtherCard.h>
#include <net.h>
#define HTTP_HEADER_OFFSET 163
#define MAX_STRINGS 10
#define MAX_STRING_LENGTH 20
#define REQUEST_EVERY_X_MS 5000
/* Setup for Ethernet Library */
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
const char website[] PROGMEM = "www.arksecurity.net16.net"; //link para o banco de dados do usuário em questão
const char device[] = "0001"; // adicionar aqui o número do dispositivo equivalente ao que aparece no Bando de Dados
char test[MAX_STRINGS][MAX_STRING_LENGTH+1];
String test2 = "9999";
//uint8_t receivedResponse;
unsigned long timer;
unsigned long timer2 = 5000;
byte Ethernet::buffer[700];
static void response_callback (byte status, word off, word len) {
for(int i=0;i<MAX_STRINGS;i++)
for(int j=0;j<=MAX_STRING_LENGTH;j++)
test[i][j] = 0;
int i_string = 0;
int i_char = 0;
int i_ethBuff = off + HTTP_HEADER_OFFSET;
char carat;
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat = (char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
if (carat == '\n')
{ // New line char = new string
if (i_string < MAX_STRINGS - 1){
i_string++;
i_char = 0;
}
else
break; // Limite de memória do Arduino
}
else
{
if (i_char < MAX_STRING_LENGTH)
{
test[i_string][i_char] = carat;
i_char++;
} // otherwise discard the char (max length of string reached)
}
}
//receivedResponse[0] = 1;
}
void setup() {
Serial.begin(57600);
if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0)
{
Serial.println("Failed to access Ethernet controller");
while(1);
}
else
Serial.println("Ethernet controller initialized");
Serial.println();
if (!ether.dhcpSetup())
{
Serial.println("Failed to get configuration from DHCP");
while(1);
}
else
Serial.println("DHCP configuration done");
if (!ether.dnsLookup(website))
{
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
timer = millis() - timer2;
}
void loop() {
word pos = ether.packetLoop(ether.packetReceive());
if (millis() - timer > timer2)
{
ether.browseUrl(PSTR("/DevicesQuery.php?device="),device , website, response_callback);
if(test[0][0] != 0){
Serial.println("Data Received");
Serial.println(test[0]);
Serial.println(test[1]);
Serial.println(test[2]);
Serial.println(test[3]);
Serial.println(test[4]);
Serial.println(test[5]);
timer2 = 500000;
}
else{
Serial.println("Nothing");
timer2 = 5000;
}
timer += timer2;
}
Edit5:我将这部分添加到我的代码中,所以我也可以将数据发送到我的服务器,但我出于某种原因只发送了一个数据,即使我很难使用循环。为什么会这样?
代码:
for(int i = 0; i < countRegister ; i++)
{
register[i].toCharArray(tempRegister, 80);
ether.browserUrl(PTSR("/log.php"), tempRegister , browser_callback);
}
static void browser_callback (byte status, word off, word len)
{
Serial.println("Data sent");
}
答案 0 :(得分:0)
首先,所有这一切都没有经过测试。我还在等待我的董事会到来,所以...我正在使用我在互联网上找到的一套很好的教程(但是他们使用的是意大利语)。特别是here是关于如何从服务器获取数据的教程。
好的,首先必须设置ENC28J60电路板,其中包含所有必需的参数,例如MAC地址和IP配置。在我使用DHCP的示例中,您可以使用静态配置(希望您知道如何操作)。
然后你必须检查你是否可以解析网站的名称(DNS查询) - 不确定这是否真的有必要。)
然后只需轮询网站(在此示例中每5秒一次)并分析数据包。
以下是代码:
#include <EtherCard.h>
#define HTTP_HEADER_OFFSET 0
static byte mymac[] = {0x12,0x34,0x56,0x78,0x90,0xAB};
char website[] PROGMEM = "www.yourwebsite.com";
byte Ethernet::buffer[700];
static uint32_t timer = 0;
static void response_callback (byte status, word off, word len) {
Serial.print((const char*) Ethernet::buffer + off + HTTP_HEADER_OFFSET);
}
void setup () {
Serial.begin(57600);
if (!ether.begin(sizeof Ethernet::buffer, mymac, 10))
{
Serial.println("Failed to access Ethernet controller");
while(1);
}
else
Serial.println("Ethernet controller initialized");
Serial.println();
if (!ether.dhcpSetup())
{
Serial.println("Failed to get configuration from DHCP");
while(1);
}
else
Serial.println("DHCP configuration done");
if (!ether.dnsLookup(website))
{
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
}
void loop() {
ether.packetLoop(ether.packetReceive());
if (millis() > timer) {
timer = millis() + 5000;
ether.browseUrl("/", "yourpage.php", website, response_callback);
}
}
这个草图在串行控制台上的输出将是这样的(图片来自我之前提到的教程)
正如您所看到的,在实际页面之前有一个标题。你只需计算它们有多少个字符,并将此值放在HTTP_HEADER_OFFSET中。
另一种方法,如果此标题不同,则在当前消息之前添加一些内容(例如将所有内容包装在<body>
标记中)并搜索它。
无论如何,在response_callback
功能中,您将拥有Ethernet::buffer + off + header_offset
中的所有数据。然后你必须解析它并把它放到一个数组中,但我希望你能自己做。
编辑:
要使用静态IP,您必须以这种方式设置:
static byte myip[] = {192,168,1,10};
static byte gatewayip[] = {192,168,1,1};
//static byte dnsip[] = {8,8,8,8}; // Google DNS; change if you want to use another
static byte dnsip[] = {192,168,1,1}; // The OP said that with google dns something was not working
...
ether.staticSetup(myip, gatewayip, dnsip);
EDIT2:
好吧,因为你已经将数据作为字符串,所以很容易将它分成块。一种可能的解决方案:
#define MAX_STRINGS 10
#define MAX_STRING_LENGTH 10
char test[MAX_STRINGS][MAX_STRING_LENGTH+1];
static void response_callback (byte status, word off, word len) {
for(int i=0;i<MAX_STRINGS;i++)
for(int j=0;j<=MAX_STRING_LENGTH;j++)
test[i][j] = 0;
int i_string = 0;
int i_char = 0;
int i_ethBuff = off + HTTP_HEADER_OFFSET;
char carat;
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat = (char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
if (carat == '\n')
{ // New line char = new string
if (i_string < MAX_STRINGS-1)
i_string++;
else
break; // Too many strings; discarding all the other ones
}
else
{
if (i_char < MAX_STRING_LENGTH)
{
test[i_string][i_char] = carat;
i_char++;
} // otherwise discard the char (max length of string reached
}
}
}
如果其中一个长度小于255,则可以将int计数器更改为uint8_t。
EDIT3:
要将字符串检测为分隔符,它有点棘手。例如,要检测"<br>"
,您可以:
char separator[] = "<br>";
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat = (char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
if (i_char < MAX_STRING_LENGTH)
{
test[i_string][i_char] = carat;
i_char++;
uint8_t stringDetected = 0;
if (i_char >= sizeof(separator))
{
int i_sep;
stringDetected = 1;
for (i_sep = 0; i_sep < sizeof(separator) && (stringDetected); i_sep++)
{ // You can try to detect it
if (test[i_string][i_char - sizeof(separator) + i_sep] != separator[i_sep]);
stringDetected = 0;
}
}
if (stringDetected)
{
test[i_string][i_char - sizeof(separator)] = '\0';
if (i_string < MAX_STRINGS-1)
i_string++;
else
break; // Too many strings; discarding all the other ones
}
}
}
我希望这有效(也许你必须通过+/- 1校正计数器(不知道sizeof是否会返回尾随\ 0)。
请记住增加单个字符串的空间(他们也需要存储分隔符)
编辑4:
至于错误的测试,我认为是因为你尚未收到回复。在测试之前,您可以等待响应回来。
此外,我注意到计时器中有一个小错误:你必须使它长整齐,并测试millis() - 计时器而不是millis()&gt;计时器,否则你会在定时器翻转时遇到问题。我在这段代码中修复了它:
// Before the setup
#define REQUEST_EVERY_X_MS 5000
uint8_t receivedResponse;
unsigned long timer;
// At the end of setup
timer = millis() - REQUEST_EVERY_X_MS;
// Inside response callback
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat = (char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
...
}
receivedResponse = 1;
// In the main loop
if (millis() - timer > REQUEST_EVERY_X_MS)
{
timer += REQUEST_EVERY_X_MS;
receivedResponse = 0;
ether.browseUrl(PSTR("/DevicesQuery.php?device="),device , website, response_callback);
while (!receivedResponse);
for(int i=0; i < 20 - 1; i++)
{
comp[i] = test[i];
if(test2.equals(comp[i]))
Serial.println("OK");
else
Serial.println("Wrong");
}
}
至于每天执行一次,如果你想在午夜准确执行它,你需要一些方法来跟踪时间(例如RTC或使用带以太网的NTP协议)。这不是很简单,但你可以找到很多关于如何使用RTC的例子。
另一方面,如果你想每天只执行一次(无论时间),只需将define REQUEST_EVERY_X_MS
更改为正确的值(24h = 1440 min = 86400s = 86400000ms,所以{ {1}})它应该在你打开它然后每24小时运行一次。您可以使用最长为4294967294毫秒的时段,或大约49天。
编辑5:
好的,看看其他人的想法(主要来自OP在下面的评论中提供的链接)它看起来是
所以..试着为后续调用实现这个:
#define REQUEST_EVERY_X_MS 86400000
希望这能解决所有问题;)