Arduino mkr1000 does not Serial print upon GET using aRest library - rest

I'm trying to create a REST server on an arduino mkr1000. upon searching google i came upon the aRest library which handles most of the stuff i need.
aRest library documentation
So i created a sample sketch based on the guides. Here is the code:
#include < SPI.h >
#include < WiFi101.h >
#include < aREST.h >
aREST rest = aREST();
int status = WL_IDLE_STATUS;
WiFiServer restServer(80);
char ssid[] = "user"; // not actual username
char pass[] = "pass"; // not actual password
int clapMode(String data){
Serial.println("Request Recieved: " + data);
}
void setup() {
Serial.begin(115200);
rest.set_id("000");
rest.set_name("MKR1000");
rest.function("test",clapMode);
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP
network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println();
// you're connected now, so print out the status:
printWifiStatus();
// Start server
restServer.begin();
Serial.println(F("Listening for connections..."));
}
void loop() {
WiFiClient client = restServer.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
IPAddress subnet = WiFi.subnetMask();
Serial.print("Netmask: ");
Serial.println(subnet);
IPAddress gateway = WiFi.gatewayIP();
Serial.print("Gateway: ");
Serial.println(gateway);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
The code works mostly. Upon using POSTMAN to perform a GET the arduino is able to give the appropriate response.
Now for the part that is not working is the endpoint i just have created using this code
rest.function("test",clapMode);
upon performing a GET in postman, the arduino is able to give a response, but it should perform this code
int clapMode(String data){
Serial.println("Request Recieved: " + data);
}
but on my serial Monitor i am not getting anything.
Also i could not find on how to tailor the response of the arduino from the request. How do i it ?
Thank you very much

You have to send the request to <host>/test?params=0, not <host>/clapMode.
Furthermore, you can modify the ID and name with
rest.set_id("device ID");
rest.set_name("device name");
and add variables with
rest.variable("variable name", &variable);
The response is hard-coded into the library, therefore if you want to add/remove other stuff, you have to edit the library by yourself.

Related

Failure to send data from client to server in ESP-01 WiFi

Using the ESP8266WiFi library, I have two ESP-01's/ESP8266's connected over WiFi. It works perfectly when the client sends a request (all non HTML!) to the server (using port 5000 - to prevent any confusion with HTTP, FTP etc.). But I cannot get the client to receive an answer back from the server. Now, in the ESP8266WiFi library (3.0.2) there is a note that server.write() is not implemented, and that I should use server.accept() instead of server.available(); though I did not see any applicable examples using server.accept(), but I see many examples using client.print() so I try to follow those - to no avail, yet. What I am doing is the following: 1. establish connectivity to the WiFi; 2. have the client connect to the server and send two bytes to the server. 3. Do a digital write to a pin of the server-ESP8266.(this toggles a relay, which works fine) 4. write back from server to client that the digital write has been done. On the client side, after writing to the server, I run in a loop for some 10 seconds trying to receive something from the server, which never comes. Then I cycle back to the beginning, and the client asks to toggle the relay again - this runs nicely for hours.
Any insights here on what I should do differently are highly appreciated. I really want to be able to get some acknowledgement back to the client once the server has toggled the relay. Or if someone has a working example with server.accept() - I would try that too.
Client side code:
int pin_value;
uint8_t ip[4];
void setup()
{
Serial.begin(115200);
ip[0]=10;
ip[1]=0;
ip[2]=0;
ip[3]=6;
//We connect to the WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
//Wait until connected
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.print("Client - ");
Serial.println("WiFi connected");
}
void loop(){
//Variable that we will use to connect to the server
WiFiClient client;
//if not able to connect, return.
if (!client.connect(ip, SERVER_PORT)){ return; }
// We create a buffer to put the send data
uint8_t buffer[Protocol::BUFFER_SIZE];
//We put the pin number in the buffer
// whose state we want to send
buffer[Protocol::PIN] = RELAY;
//put the current state of the pin in the send buffer
buffer[Protocol::VALUE] = pin_value;
//We send the data to the server
client.write(buffer, Protocol::BUFFER_SIZE);
// try to read the answer from the server for about 10 seconds
int nr_of_tries = 10000;
while (client.connected() && nr_of_tries > 0)
{if (client.available())
{ String line = client.readStringUntil('\n');
nr_of_tries = 0;
Serial.print("line= ");
Serial.println(line);
}
else
{delay(1);
nr_of_tries=nr_of_tries-1;
}
}
Serial.print("nr of tries= ");
Serial.println(nr_of_tries);
Serial.print("connected: ");
Serial.println(client.connected());
client.flush();
client.stop();
Serial.println(" change sent");
if (pin_value == 0)
{pin_value =1;
Serial.println("Pin_value set to 1");
}
else
{pin_value=0;
Serial.println("Pin_value set to 0");}
delay(10000);
}
Server side code:
WiFiServer server(SERVER_PORT);
void setup()
{
Serial.begin(115200); // must have the same baud rate as the serial monitor
pinMode(RELAY,OUTPUT);
digitalWrite(RELAY, LOW);
// Connect to the WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println("Server - ");
Serial.println("WiFi connected");
// Set this ESP to behave as a WiFi Access Point
// WiFi.mode(WIFI_AP);
// set SSID and Password to connect to this ESP
// WiFi.softAP(SSID, PASSWORD);
// Start the server
server.begin();
Serial.println("Server started");
// Output of the IP address
Serial.print("Use this IP to connect: ");
Serial.println(WiFi.localIP());
}
void loop()
{
// Check if there is any client connecting
WiFiClient client = server.available();
if (client)
{
//Serial.println("Client detected");
//If the client has data he wants to send us
//check for a second or so as transmission can take time
int nr_of_tries = 1000;
while(!client.available() && nr_of_tries > 0)
{ nr_of_tries=nr_of_tries-1;
delay(1);
}
if (client.available())
{
// Serial.println(" Client data");
// create a buffer to put the data to be received
uint8_t buffer[Protocol::BUFFER_SIZE];
// We put the data sent by the client in the buffer
// but do not read more than the buffer length.
int len = client.read(buffer, Protocol::BUFFER_SIZE);
// retrieve which pin number the client sent
int pinNumber = buffer[Protocol::PIN];
Serial.print("Pin Number: ");
Serial.println(pinNumber);
// retrieve the value of this pin
int value = buffer[Protocol::VALUE];
Serial.print("Value: ");
Serial.println(value);
// Set the pin indicated by the received pin number in output mode
// but only if the pin is the GPIO0 pin!
if (pinNumber == RELAY)
{ pinMode(pinNumber, OUTPUT);
// Set the pin indicated by the received pin number to the passed value
digitalWrite(pinNumber, value);
}
// tell the client that the relay has been set or reset.
size_t i;
if (value == 0) {
i=server.println("Set");
Serial.print("i= ");
Serial.println(i);
}
else {
i=server.println("Reset");
Serial.print("i= ");
Serial.println(i);
}
}
}
//Close the connection with the client
//client.stop();
}
Common definitions:
#include <ESP8266WiFi.h>
const char* ssid = "blablabla";
const char* password = "blublublu";
#define SERVER_PORT 5000
#define RELAY 0
//Protocol that the Server and Client will use to communicate
enum Protocol{
PIN, // Pin whose state you want to change
VALUE, // State to which the pin should go (HIGH = 1 or LOW = 0)
BUFFER_SIZE // The size of our protocol. IMPORTANT: always leave it as the last item of the enum
};
Solved! By changing server.println("Set"); into client.println("Set") and doing the same for the transmission of "Reset" a few lines lower in the server side code it works!

asio server reads data only once

Here is my server side read code.
void ServerSession::doRead()
{
//note sbuf_ is std::string
asio::async_read_until(socket_, asio::dynamic_buffer(sbuf_), "\n",
[this](std::error_code ec, std::size_t length)
{
if(!ec || ec == asio::error::eof)
{
printf("length = %lu [S] received str size = %lu, Client sent : %s\n", length, sbuf_.size(), sbuf_.data());
if(sbuf_.size() > 0)
{
std::string msg{sbuf_};
addMessageToQueue(std::move(msg));
sbuf_.clear();
}
}
else
{
socket_.close(); //force close the socket upon read error.
}
});
}
I run it and connect using a TCP client, I send some text say "A 1" server receives it correctly. but when I send a next string say "B 12" it doesn't receive it.
I tried multiple connections. for all the connections that I establish with server, server receives first string that client sends, and after that there is a silence. I added many log statements in the code, but I am not able to see them when I try to send second string.

How to get the MAC adress of an access point when esp8266 is in client (station) mode?

I would like my esp8266 to retrieve the mac address of the AP it`s connected to as a client (station), following this discussion on How to get Access Point MAC adress.
Here is my code:
#include <ESP8266WiFi.h>
const char* ssid = "somrmthing";
const char* password = "somrmthing"; //
const char* host = "aubs.gear.host"; //create webserver & correct address
uint8_t MAC_array[6];
char MAC_char[18];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(100);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
int value = 0;
void loop() {
// put your main code here, to run repeatedly:
/*
* http://stackoverflow.com/questions/34078497/esp8266-wificlient-simple-http-get
*/
delay(30000);
++value;
/*
* https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino
*/
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
// getting the mac address http://bbs.espressif.com/viewtopic.php?f=15&t=3102&p=10569&hilit=Access+Point+MAC+adress&sid=a68dcff311ea05ece032126d6f93902f#p10569
void wifi_handle_event_cb(System_Event_t *evt)
{
os_printf("event %x\n", evt->event);
switch (evt->event){
case EVENT_STAMODE_CONNECTED:
os_printf("connect to ssid %s, channel %d\n", evt->event_info.connected.ssid, evt->event_info.connected.channel);
os_printf("AP MAC address is %s\n", evt->event_info.connected.bssid);
break;
case ....
....
}
}
//old wrong MAC ADDRESS
// getting the mac address //Serial.println(MAC_char); - See more at: http://www.esp8266.com/viewtopic.php?f=29&t=3587#sthash.bwWPqcc6.dpuf
WiFi.macAddress(MAC_array);
for (int i = 0; i < sizeof(MAC_array); ++i){
sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
}
// We now create a URI for the request
String url = "/store.php"; // String url = "/input/";
url += "?dev_id=";
url += "BikeShare9";
url += "&hoster=";
url += MAC_char;
url += "&ip_add=";
url += WiFi.localIP();
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
}
For void wifi_handle_event_cb(System_Event_t *evt) I get the following error:
C:\Users\Tinotenda\Desktop\ver1.0\ver1.0.ino: In function 'void setup()':
ver1.0:48: error: a function-definition is not allowed here before '{' token
void loop() {
^
ver1.0:129: error: expected '}' at end of input
}
^
exit status 1
a function-definition is not allowed here before '{' token
How can I fix that?
Your setup()-function doesn't have it's closing bracket.
You should also place all the global variables at the top, or make them static inside the function that uses them. (ref: int value = 0 ,although I don't know what you're using the variable for)
Furthermore, avoid the user of very long delays. delay(30000)causes the ESP8266 IP-stack to behave strangely. You should better use the millis-structure:
static unsigned long lastMillis = 0;
if (millis() - lastMillis < 30 * 1000UL) {
lastMillis = millis();
//do your stuff
}
This answer should help other beginners:
Copy and pasting code without understanding the basics is never a good idea.
Basic structure of an Arduino program (=sketch)
Definitions, global vars
int value = 0;
should be placed there
SETUP
void setup(){
All one time functions, initalization routines, etc
}
LOOP
void loop(){
recuring tasks call functions from here in the above example
Call the example function like this
wifi_handle_event_cb(SomeParamToHandOver);
NEVER use delay - it stops processing for the given time
Not a good idea in server client scenarios ->
look for blink without delay in the Arduino examples for more
Never use while in here it may lead to dead locks
}
functions/modules you call from the setup or loop
void wifi_handle_event_cb(System_Event_t *evt) {
Exmple from the question
}
plus all remarks in the answer above
All beginners should start with https://www.arduino.cc/en/Tutorial/BuiltInExamples

Opening a UDP connection in Veins toward external server

I'm using Veins 4.4 and I need to store some results in an outer server, so I would like to open a UDP connection toward it.
I've read several posts about using a TCP connection for the mobility in Veins,and I understood I should resort to the Inet module to open a connection.
Although I don't need it for the mobility, but to send data to an external server.
Is there any suggestion?
I was trying to use the method processCommandFromApp method from inet/src/transport/UDP.cc class:
void UDP::processCommandFromApp(cMessage *msg)
{
switch (msg->getKind())
{
case UDP_C_BIND: {
UDPBindCommand *ctrl = check_and_cast<UDPBindCommand*>(msg->getControlInfo());
bind(ctrl->getSockId(), msg->getArrivalGate()->getIndex(), ctrl->getLocalAddr(), ctrl->getLocalPort());
break;
}
case UDP_C_CONNECT: {
UDPConnectCommand *ctrl = check_and_cast<UDPConnectCommand*>(msg->getControlInfo());
connect(ctrl->getSockId(), msg->getArrivalGate()->getIndex(), ctrl->getRemoteAddr(), ctrl->getRemotePort());
break;
}
case UDP_C_CLOSE: {
UDPCloseCommand *ctrl = check_and_cast<UDPCloseCommand*>(msg->getControlInfo());
close(ctrl->getSockId());
break;
}
case UDP_C_SETOPTION: {
UDPSetOptionCommand *ctrl = check_and_cast<UDPSetOptionCommand *>(msg->getControlInfo());
SockDesc *sd = getOrCreateSocket(ctrl->getSockId(), msg->getArrivalGate()->getIndex());
if (dynamic_cast<UDPSetTimeToLiveCommand*>(ctrl))
setTimeToLive(sd, ((UDPSetTimeToLiveCommand*)ctrl)->getTtl());
else if (dynamic_cast<UDPSetTypeOfServiceCommand*>(ctrl))
setTypeOfService(sd, ((UDPSetTypeOfServiceCommand*)ctrl)->getTos());
else if (dynamic_cast<UDPSetBroadcastCommand*>(ctrl))
setBroadcast(sd, ((UDPSetBroadcastCommand*)ctrl)->getBroadcast());
else if (dynamic_cast<UDPSetMulticastInterfaceCommand*>(ctrl))
setMulticastOutputInterface(sd, ((UDPSetMulticastInterfaceCommand*)ctrl)->getInterfaceId());
else if (dynamic_cast<UDPSetMulticastLoopCommand*>(ctrl))
setMulticastLoop(sd, ((UDPSetMulticastLoopCommand*)ctrl)->getLoop());
else if (dynamic_cast<UDPSetReuseAddressCommand*>(ctrl))
setReuseAddress(sd, ((UDPSetReuseAddressCommand*)ctrl)->getReuseAddress());
else if (dynamic_cast<UDPJoinMulticastGroupsCommand*>(ctrl))
{
UDPJoinMulticastGroupsCommand *cmd = (UDPJoinMulticastGroupsCommand*)ctrl;
std::vector<IPvXAddress> addresses;
std::vector<int> interfaceIds;
for (int i = 0; i < (int)cmd->getMulticastAddrArraySize(); i++)
addresses.push_back(cmd->getMulticastAddr(i));
for (int i = 0; i < (int)cmd->getInterfaceIdArraySize(); i++)
interfaceIds.push_back(cmd->getInterfaceId(i));
joinMulticastGroups(sd, addresses, interfaceIds);
}
else if (dynamic_cast<UDPLeaveMulticastGroupsCommand*>(ctrl))
{
UDPLeaveMulticastGroupsCommand *cmd = (UDPLeaveMulticastGroupsCommand*)ctrl;
std::vector<IPvXAddress> addresses;
for (int i = 0; i < (int)cmd->getMulticastAddrArraySize(); i++)
addresses.push_back(cmd->getMulticastAddr(i));
leaveMulticastGroups(sd, addresses);
}
else
throw cRuntimeError("Unknown subclass of UDPSetOptionCommand received from app: %s", ctrl->getClassName());
break;
}
default: {
throw cRuntimeError("Unknown command code (message kind) %d received from app", msg->getKind());
}
}
delete msg; // also deletes control info in it
}
I included the inet path as follows:
#include <inet/src/transport/udp/UDP.h>
and I call it as follows, by passing as input UDP_C_CONNECT message.:
cMessage *UDP_C_CONNECT;
void Inet::UDP::processCommandFromApp(UDP_C_CONNECT);
But when I run the simulation, it crashes, returning this error:
Errors occurred during the build.
Errors running builder 'OMNeT++ Makefile Builder' on project 'veins'.
java.lang.NullPointerException
1) Is there the correct way to set up the required connection?
2) Why I'm getting this error as soon as I include the inet path?
UPDATE
I also tried another way to establish the connection:
std::string host;
host = "16777343";
int port = 5144;
Veins::TraCIConnection* connection;
connection = TraCIConnection::connect(host.c_str(), port);
but as soon as it load the plugin, then it's like it is waiting for something at time 0.0 without starting the generation of the nodes.
Thanks for helping
Simulations using OMNeT++ are C++ programs, so you can use the full range of libraries and system calls available to any C++ program. If you want to open a UDP connection to some other computer on your network, just create a UDP socket as you would in any C++ program, then send the data whenever needed.
Maybe the easiest way to go about writing this is to
start with a plain C++ program that has nothing to do with OMNeT++
move the part of the program that has to run before everything else into the initialize method of a module in your simulation, the rest to a handleMessage method.

Unable to transfer data between two ESP8266

I am trying to connect two esp 8266 (Wi-fi) module with each other one as hotspot (server) using Wifi of ESP12 E module 8266 and other is (client).I am Using Arduino IDE for programming
my server starts properly and client is connected to server but when I send data from client to server I got nothing. I google about data transfer between client and server, but nothing is there for client data transfer using Arduino coding.
Here is My code in Arduino
server side code
#include <ESP8266WiFi.h>
WiFiServer server(80); //Initialize the server on Port 80
void setup()
{
WiFi.mode(WIFI_AP); // ESP8266-12E is an AccessPoint
WiFi.softAP("11111111", "12345678"); // Provide the (SSID, password)
server.begin(); // Start the Server
Serial.begin(115200); //Start communication between the ESP8266-12E and the monitor window
IPAddress HTTPS_ServerIP= WiFi.softAPIP(); // Obtain the IP of the Server
Serial.print("Server IP is: "); // Print the IP to the monitor window
Serial.println(HTTPS_ServerIP);
}
void loop()
{
WiFiClient client = server.available();
if (!client)
{
return;
}
//Looking under the hood
Serial.println("Somebody has connected :)");
}
client side code
#include <ESP8266WiFi.h>
const char *ssid = "11111111";
const char *password = "12345678";
const char *host = "192.168.4.2";
const int httpPort = 80;
void setup()
{
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop()
{
delay(8000);
Serial.print("connecting to ");
Serial.println(host);
WiFiClient client;
client.connect(host,httpPort);
if (!client.connect(host,httpPort))
{
Serial.println("connection failed");
return;
}
else
client.print("connected");
}
can any one suggest me how to transfer data from client to server
The Arduino ESP8266 class WiFiClient inherits from Stream, so, all stream functions are available to you. You can find documentation for that class here.
You could use readBytes, readString, or just plain read to do what you want.
Additionally, if you do plan to use HTTP, you may be interested in using the libraries ESP8266WebServer and ESP8266HTTPClient which come with your ESP8266 Arduino environment and implement a lot of this low level code you are attempting to write. You can find examples for the server here, and the client here