ESP8266 Sniffing and sending Mac address - httprequest

I'm trying to make my ESP8266 sniffing nearby devices, then posting them by with a HTTP request. With purpose is to record when my roommate and I are at home. Then in the future, trigger certain tasks like turning on/off the lights if we're home or not. I don't care at all about the packets content just the mac addresses.
So fare I've found this, script that prints out the mac adresses for nearby devices, created by kalanda: esp8266-sniffer.
Aswell as this HTTP posting script ESP8266 http get requests.
I've tried to combine those two and in the callback function make the ESP send the found data, but doesn't look like the ESP establish the wifi connection.
I tried using different WIFI modes: STATION_MODE, SOFTAP_MODE, STATIONAP_MODE. None of them worked for both sniffing and http request at the same time. I know that the STATIONAP_MODE do have some flaws. What I've found is that it has to switch both somehow, but unfortunately I'm not a ESP expert and don't know how this can be done.
Here is my code(srry for any rubbish coding on my side):
#include <ESP8266WiFi.h> // added this
#include <ESP8266HTTPClient.h> // added this
const char* ssid = "**********"; // Wifi SSID
const char* password = "**********"; // Wifi Password
String main_url = "http://*********.php?"; // Website url to post the information
String temp_url = ""; // Url with information
extern "C" {
#include <user_interface.h>
}
#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_PROBE_REQUEST 0x04
struct RxControl {
signed rssi:8; // signal intensity of packet
unsigned rate:4;
unsigned is_group:1;
unsigned:1;
unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
unsigned legacy_length:12; // if not 11n packet, shows length of packet.
unsigned damatch0:1;
unsigned damatch1:1;
unsigned bssidmatch0:1;
unsigned bssidmatch1:1;
unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
unsigned HT_length:16;// if is 11n packet, shows length of packet.
unsigned Smoothing:1;
unsigned Not_Sounding:1;
unsigned:1;
unsigned Aggregation:1;
unsigned STBC:2;
unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
unsigned SGI:1;
unsigned rxend_state:8;
unsigned ampdu_cnt:8;
unsigned channel:4; //which channel this packet in.
unsigned:12;
};
struct SnifferPacket{
struct RxControl rx_ctrl;
uint8_t data[DATA_LENGTH];
uint16_t cnt;
uint16_t len;
};
static void showMetadata(SnifferPacket *snifferPacket) {
unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t version = (frameControl & 0b0000000000000011) >> 0;
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t toDS = (frameControl & 0b0000000100000000) >> 8;
uint8_t fromDS = (frameControl & 0b0000001000000000) >> 9;
// Only look for probe request packets
if (frameType != TYPE_MANAGEMENT ||
frameSubType != SUBTYPE_PROBE_REQUEST)
return;
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: ");
Serial.print(wifi_get_channel());
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);
Serial.print(" Peer MAC: ");
Serial.print(addr);
uint8_t SSID_length = snifferPacket->data[25];
Serial.print(" SSID: ");
printDataSpan(26, SSID_length, snifferPacket->data);
Serial.println();
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{
HTTPClient http; //Declare an object of class HTTPClient
temp_url = main_url;
temp_url = temp_url + "mac=30:a8:db:96:a4:75";
temp_url = temp_url + "&rssi=-90";
temp_url = temp_url + "&ssid=none";
http.begin(temp_url); //Specify request destination
int httpCode = http.GET(); //Send the request
temp_url = "";
if (httpCode > 0)
{ //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println(payload); //Print the response payload
}
http.end(); //Close connection
}
else
{
Serial.println("Wifi connection failed"); //Prints out this
}
}
/**
* Callback for promiscuous mode
*/
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
for(uint16_t i = start; i < DATA_LENGTH && i < start+size; i++) {
Serial.write(data[i]);
}
}
static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}
#define CHANNEL_HOP_INTERVAL_MS 1000
static os_timer_t channelHop_timer;
/**
* Callback for channel hoping
*/
void channelHop()
{
// hoping channels 1-14
uint8 new_channel = wifi_get_channel() + 1;
if (new_channel > 14)
new_channel = 1;
wifi_set_channel(new_channel);
}
#define DISABLE 0
#define ENABLE 1
void setup() {
// set the WiFi chip to "promiscuous" mode aka monitor mode
Serial.begin(115200);
delay(10);
wifi_set_opmode(STATION_MODE);
wifi_set_channel(1);
wifi_promiscuous_enable(DISABLE);
delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);
delay(10);
wifi_promiscuous_enable(ENABLE);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Connecting..");
}
Serial.println("");
Serial.println("Connected..");
// setup the channel hoping callback timer
os_timer_disarm(&channelHop_timer);
os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
}
void loop() {
delay(10);
}

Here's the code which aggregates probe requests (MAC addresses and RSSIs) for 3 seconds and then sends them to specified server's endpoint using json (WIFI_AP_STA mode):
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <vector>
const char* apSsid = "ap-ssid";
const char* apPassword = "ap-password";
const char* clientSsid = "client-ssid";
const char* clientPassword = "client-password";
HTTPClient http;
WiFiEventHandler probeRequestPrintHandler;
String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
std::vector<WiFiEventSoftAPModeProbeRequestReceived> myList;
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
myList.push_back(evt);
}
void setup() {
Serial.begin(115200);
Serial.println("Hello!");
// Don't save WiFi configuration in flash - optional
WiFi.persistent(false);
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(apSsid, apPassword);
WiFi.begin(clientSsid, clientPassword);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println("");
probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
}
void loop() {
delay(3000);
String json = "";
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
JsonArray& probes = root.createNestedArray("probes");
for(WiFiEventSoftAPModeProbeRequestReceived w : myList){
JsonObject& probe = probes.createNestedObject();
probe["address"] = macToString(w.mac);
probe["rssi"] = w.rssi;
}
myList.clear();
root.printTo(json);
Serial.println("json:" + json);
http.begin("http://example.com/api/v1/probe");
http.addHeader("Content-Type", "application/json");
http.POST(json);
http.end();
}
Remember to use the latest version (actually a pre-release - 2.4.0-rc1 or newer) of arduino-esp8266 library since those WiFiEvents were just recently added.
You can download ArduinoJson library using Library Manager (Sketch -> Include Library -> Manage Libraries...) if you don't have that already.

Related

ESP8266 WIFI Connection lost after Acces Point reboot

Heyho,
at first, I am no programmer - it's just my hobby :)
I have a cistern in my garden and I want to measure the level of it with an ESP8266 and an ultrasonic sensor.
I am sending the data via mqtt to my mqtt broker.
Everything working well but when my accesspoint is rebooting two times a day and after that reboot the ESP8266 doesn't connect to the WIFI again.
What I've done so far:
setting the WiFi.setAutoReconnect(true); to true (find that in the Internet)
call the function setup(); in void loop() again
So, I think I have a mistake in thinking with that problem.
Heres my code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ultrasonic.h>
Ultrasonic ultrasonic(12, 13);
const char* ssid = "XXX"; // Enter your WiFi name
const char* password = "XXX"; // Enter WiFi password
const char* mqttServer = "XXX";
const int mqttPort = 1883;
const char* mqttUser = "XXX";
const char* mqttPassword = "XXX";
#define abstand_topic "home/zisterne/fuellstand"
#define abstand_topic_2 "home/zisterne/mittl_fuellstand"
const int RunningAverageCount = 24; // Anzahl der in den Laufenden-Mettelwert aufgenommenen Messungen
float RunningAverageBuffer[RunningAverageCount];
int NextRunningAverage;
unsigned long previousMillis = 0;
unsigned long interval = 30000;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
// //Sensor auslesen und übergeben
// int Sensor = ultrasonic.distanceRead();
// char Abstand[10];
// itoa(Sensor,Abstand,10);
//
// Serial.println(ultrasonic.distanceRead());
// client.publish(abstand_topic, Abstand);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void loop() {
client.loop();
//WLAN Reconnect
if (WiFi.status() != WL_CONNECTED) {
delay(500);
setup();
}
//Sensor auslesen und übergeben
int Sensor = ultrasonic.distanceRead();
char Abstand[10];
itoa(Sensor,Abstand,10);
Serial.println(ultrasonic.distanceRead());
client.publish(abstand_topic, Abstand);
//unsigned long minutes = 1000 * 300;
float RawDistance = ultrasonic.distanceRead();
RunningAverageBuffer[NextRunningAverage++] = RawDistance;
if (NextRunningAverage >= RunningAverageCount)
{
NextRunningAverage = 0;
}
float RunningAverageDistance = 0;
for(int i=0; i< RunningAverageCount; ++i)
{
RunningAverageDistance += RunningAverageBuffer[i];
}
RunningAverageDistance /= RunningAverageCount;
int mittelwert = RunningAverageDistance;
char mittl_Abstand[10];
itoa(mittelwert,mittl_Abstand,10);
client.publish(abstand_topic_2, mittl_Abstand);
delay(5000);
yield();
}
So, now I hope someone of you can help me with my small problem! :)
Greetings,
Philipp

Do DLLs have a lower priority that may affect ethernet functionality? Experiencing TCP retransmissions

I have some modbus ethernet tcp communications that I'm attempting to do in a DLL. I get numerous TCP Retransmissions from the target device, as seen in WireShark.
(In this image, 192.168.1.5 is the Modbus device. 192.168.1.72 is the computer)
However, when the same code is inserted directly into an application, there are no communication errors.
I'm wondering if DLLs have some sort of lower priority that can cause slower communications, or if anyone may have any insight as to why this code would run without TCP issue in an application, but not in a DLL.
Here is the dll header:
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
typedef void *eioTHandle;
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall eioConnect( unsigned short ModelId, char *Ip, eioTHandle *Handle );
#ifdef __cplusplus
}
#endif
#endif
And here is the source file:
#include "main.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdint.h>
#define EIO500_S 0
#define EIO500_MS 1000
#define eioERROR -1
#define eioSUCCESS 0
static uint8_t m_UnitId = 0xff;
static SOCKET m_Sock;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved )
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
int __stdcall eioConnect( unsigned short ModelId, char *Ip, eioTHandle *Handle )
{
WSADATA Wsa;
struct sockaddr_in Server;
int Result;
char Buffer[256];
char InBuffer[256];
// CONNECTION --------------------------------------------------------------
if (WSAStartup(MAKEWORD(2,2), &Wsa) != 0)
{
return eioERROR;
}
m_Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_Sock == INVALID_SOCKET)
{
WSACleanup();
return eioERROR;
}
Server.sin_addr.s_addr = inet_addr(Ip);
Server.sin_family = AF_INET;
Server.sin_port = htons(502);
if (connect(m_Sock, (struct sockaddr *)&Server, sizeof(Server))
== SOCKET_ERROR)
{
closesocket(m_Sock);
m_Sock = INVALID_SOCKET;
WSACleanup();
return eioERROR;
}
// -------------------------------------------------------------------------
for (int Ctr = 0; Ctr < 50000; Ctr++)
{
// SEND COMMAND --------------------------------------------------------
// 5 bytes in a Send Read Multiple Coils command.
int NumBytes = 5;
Buffer[0] = 0;
Buffer[1] = 0;
Buffer[2] = 0;
Buffer[3] = 0;
Buffer[4] = 0;
Buffer[5] = NumBytes + 1; // 1 for unit id.
Buffer[6] = m_UnitId;
// 0 = Function code.
Buffer[7] = 0x01;
// 1+2 = Address.
Buffer[8] = 0;
Buffer[9] = 8;
// 3+4 = Number of bits to read.
Buffer[10] = 0;
Buffer[11] = 8;
if (send(m_Sock, Buffer, NumBytes + 7, 0) == SOCKET_ERROR)
{
continue;
}
// ---------------------------------------------------------------------
// WAIT FOR RECEIVE ----------------------------------------------------
WSAEVENT RecvEvent;
int Ret;
RecvEvent = WSACreateEvent();
WSAEventSelect( m_Sock, RecvEvent, FD_READ );
Ret = WSAWaitForMultipleEvents(1, &RecvEvent, TRUE, 1000, FALSE);
WSAResetEvent(RecvEvent);
if (Ret == WSA_WAIT_TIMEOUT)
continue;
// -------------------------------------------------------------------------
// Check for any reply.
recv(m_Sock, InBuffer, 256, 0);
}
// DISCONNECT --------------------------------------------------------------
Result = shutdown(m_Sock, SD_SEND);
if (Result == SOCKET_ERROR)
{
closesocket(m_Sock);
WSACleanup();
m_Sock = INVALID_SOCKET;
return eioERROR;
}
// Receive until the peer closes the connection.
while (recv(m_Sock, Buffer, 256, 0) > 0);
closesocket(m_Sock);
WSACleanup();
m_Sock = INVALID_SOCKET;
// ------------------------------------------------------------------------
return eioSUCCESS;
}
I've simplified the code as much as possible. The communication is in a loop for testing. The original application would poll this data from the device.
No. From the network's perspective there's no difference in TCP segments sent some way or other. There may be a protocol prioritation though (QoS) that may cause packet drops when links are saturated.
A more likely cause could be a problem with the checksums: invalid checksums cause packet drops which in turn cause retransmissions. Possibly the API works slightly different when called from a DLL, so the checksums are calculated (correctly).

UART sending wrong characters on pic18

I'm trying to simply send characters trough my UART Interface by calling the funktion: UART_Write_Text("hello");
this is the code executed in the the uart.c file:
void UART_Init(void)
{
//115200bps deafult value for RN4678
BRGH = 0; //Setting High Baud Rat
BRG16 = 0; //8-Bit mode
SPBRG = 8; //Writing SPBRG Register
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie UART
RCSTAbits.SPEN = 1; //Enables Serial Port
RCSTAbits.CREN = 1; //Enables Reception
TXSTAbits.TXEN = 1; //Enables Transmission
}
/******************************************************************************/
//-----UART write byte
/******************************************************************************/
void UART_Write(char data)
{
while(!TRMT);
TXREG = data;
}
/******************************************************************************/
//-----UART check tx queue
/******************************************************************************/
char UART_TX_Empty(void)
{
return TRMT;
}
/******************************************************************************/
//-----UART write string
/******************************************************************************/
void UART_Write_Text(char *text)
{
for(int i=0; text[i]!='\0' || text[i] !=0x00; i++){
UART_Write(text[i]);
}
UART_Write('\n');
}
/******************************************************************************/
//-----UART data ready to read
/******************************************************************************/
char UART_Data_Ready(void)
{
return RCIF;
}
/******************************************************************************/
//-----UART read byte
/******************************************************************************/
char UART_Read(void)
{
while(!RCIF);
return RCREG;
}
/******************************************************************************/
//-----UART read string
/******************************************************************************/
void UART_Read_Text(char *Output, unsigned int length)
{
unsigned int i;
for(int i=0;i<length;i++)
Output[i] = UART_Read();
}
Now when I'm debugging it, I see that it writes the wright charakters into the TXREG. At the end it sended the following characters: 'h', 'e', 'l', 'l', 'o', '\n'.
I send them to the bluetooth module RN4678 with a baud rate of 115200bps which is also the default baud rate of the BT module. However when I read the sended character on my phone with a Bluetooth terminal i get only some characters wright and the other ones are questionmarks, so it doesn't recognise them (not always the same character unrecognised).
I already experimented with the baud rate, but it looks like its the right value I writed into the SPBRG.
I'm also polling the TRMT so there shouldn't be any collisions...
Someone knows what I'm doing wrong?
#include "Configuration_bits.h"
#include <xc.h>
#include <stdio.h>
#include <p18f67k22.h>
#include <string.h>
#include <stdlib.h>
#define _XTAL_FREQ 16000000
void UART_Init_1(){
TRISCbits.TRISC6=1; // TX1 Pin-31
TRISCbits.TRISC7=1; // RX1 Pin-32
RC1IE=1;
SPBRG1=34; // Baud Rate 115200
BAUDCON1bits.BRG16=1;
TXSTA1bits.BRGH=1;
//TXSTA 1 Register
TXSTA1bits.TX9=0; // 8-bit transmission
TXSTA1bits.TXEN=0;
TXSTA1bits.TXEN=1; // Transmit is enabled
TXSTA1bits.SYNC=0; // Asynchronous mode
TXSTA1bits.TRMT=1; // Transmit Shift Register Status bit
//RXSTA 1 Register
RCSTA1bits.SPEN=1; // Serial Port Enable bit
RCSTA1bits.RX9=0; // 8-bit reception
RCSTA1bits.CREN=1; // Continuous Receive Enable bit
}
void UART_Tx_1(unsigned char z[])
{
unsigned int uart_tx1=0;
while(z[uart_tx1]!='\0')
{
while(!TX1IF);
TXREG1=z[uart_tx1];
uart_tx1++;
}
}
void UART_Rx_1()
{
string_rx1[uart_rx1]=RCREG1;
uart_rx1++;
}
void interrupt ISR(void)
{
if(RC1IF && RC1IE) // UART_1
{
}
}
void main(void)
{
System_Initialization();
UART_Init_1();
while(1)
{
UART_Tx_1("HELLO\r\n"); // Transmit Hello
}
}

Unable to run input cature mode with SPI

I am Trying to run a web-server on AVR ATmega8 using ENC28J60 module. For this I got sample code from here. This code is working fine. Here is my code:-
#define F_CPU 8000000UL
#include <avr/io.h>
#include <string.h>
#include "ip_arp_udp_tcp.h"
#include "enc28j60.h"
#include "timeout.h"
#include "avr_compat.h"
#include "net.h"
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX
static uint8_t myip[4] = {192,168,24,39};
// listen port for www
#define MYWWWPORT 80
//// listen port for udp
#define MYUDPPORT 1200
//
#define BUFFER_SIZE 450
static uint8_t buf[BUFFER_SIZE+1];
int main(void)
{
uint16_t plen;
uint16_t dat_p;
uint8_t i=0;
uint8_t payloadlen=0;
_delay_loop_1(50);
/*initialize enc28j60*/
enc28j60Init(mymac);
enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
_delay_loop_1(50); // 12ms
enc28j60PhyWrite(PHLCON,0x476);
_delay_loop_1(50); // 12ms
//init the ethernet/ip layer:
init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT);
while(1)
{
// get the next new packet:
plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
/*plen will ne unequal to zero if there is a valid * packet (without crc error) */
if(plen==0)
{
continue;
}
// arp is broadcast if unknown but a host may also
// verify the mac address by sending it to
// a unicast address.
if(eth_type_is_arp_and_my_ip(buf,plen))
{
make_arp_answer_from_request(buf);
continue;
}
// check if ip packets (icmp or udp) are for us:
if(eth_type_is_ip_and_my_ip(buf,plen)==0)
{
continue;
}
if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V)
{
// a ping packet, let's send pong
make_echo_reply_from_request(buf,plen);
continue;
}
// tcp port www start, compare only the lower byte
if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==MYWWWPORT)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
{
make_tcp_synack_from_syn(buf);
// make_tcp_synack_from_syn does already send the syn,ack
continue;
}
if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
{
init_len_info(buf); // init some data structures
// we can possibly have no data, just ack:
dat_p=get_tcp_data_pointer();
if (dat_p==0)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
{
// finack, answer with ack
make_tcp_ack_from_any(buf);
}
// just an ack with no data, wait for next packet
continue;
}
if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0)
{
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
}
else
{
// Web Code
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<p>PLANETCAST MEDIA SERVICES LTD</p>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<body>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"text\" id=\"myurl\" name=\"url\" placeholder=\"Enter Url\"/><br>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"submit\" id=\"clickbutton\" name=\"Click Here\" />"));
plen=fill_tcp_data_p(buf,plen,PSTR("<script type=\"text/javascript\">"));
plen=fill_tcp_data_p(buf,plen,PSTR("document.getElementById(\"clickbutton\").onclick = function(){"));
plen=fill_tcp_data_p(buf,plen,PSTR("var url = document.getElementById(\"myurl\").value;"));
plen=fill_tcp_data_p(buf,plen,PSTR("location.href=url;"));
plen=fill_tcp_data_p(buf,plen,PSTR("};"));
plen=fill_tcp_data_p(buf,plen,PSTR("</script>"));
plen=fill_tcp_data_p(buf,plen,PSTR("</body"));
}
make_tcp_ack_from_any(buf); // send ack for http get
make_tcp_ack_with_data(buf,plen); // send data
continue;
}
}
// udp interface:
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V)
{
payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
// the received command has to start with t and be 4 char long
// e.g "test\0"
if (buf[UDP_DATA_P]=='t' && payloadlen==5)
{
make_udp_reply_from_request(buf,"hello",6,MYUDPPORT);
}
}
}
return (0);
}
Now I want to add Input Capture Mode , so I add interrupt header file then start Input capture mode in main() and then introduce sei() function. Now My code look like this:-
#define F_CPU 8000000UL
#include <avr/io.h>
#include <string.h>
#include "ip_arp_udp_tcp.h"
#include "enc28j60.h"
#include "timeout.h"
#include "avr_compat.h"
#include "net.h"
#include <avr/interrupt.h>
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX
static uint8_t myip[4] = {192,168,24,39};
// listen port for www
#define MYWWWPORT 80
//// listen port for udp
#define MYUDPPORT 1200
//
#define BUFFER_SIZE 450
static uint8_t buf[BUFFER_SIZE+1];
int main(void)
{
TCCR1A = 0;
TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS11);
TIMSK = (1<<TICIE1);
TCNT1 = 0;
sei();
uint16_t plen;
uint16_t dat_p;
uint8_t i=0;
uint8_t payloadlen=0;
_delay_loop_1(50);
/*initialize enc28j60*/
enc28j60Init(mymac);
enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
_delay_loop_1(50); // 12ms
enc28j60PhyWrite(PHLCON,0x476);
_delay_loop_1(50); // 12ms
//init the ethernet/ip layer:
init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT);
while(1)
{
// get the next new packet:
plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
/*plen will ne unequal to zero if there is a valid * packet (without crc error) */
if(plen==0)
{
continue;
}
// arp is broadcast if unknown but a host may also
// verify the mac address by sending it to
// a unicast address.
if(eth_type_is_arp_and_my_ip(buf,plen))
{
make_arp_answer_from_request(buf);
continue;
}
// check if ip packets (icmp or udp) are for us:
if(eth_type_is_ip_and_my_ip(buf,plen)==0)
{
continue;
}
if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V)
{
// a ping packet, let's send pong
make_echo_reply_from_request(buf,plen);
continue;
}
// tcp port www start, compare only the lower byte
if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==MYWWWPORT)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
{
make_tcp_synack_from_syn(buf);
// make_tcp_synack_from_syn does already send the syn,ack
continue;
}
if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
{
init_len_info(buf); // init some data structures
// we can possibly have no data, just ack:
dat_p=get_tcp_data_pointer();
if (dat_p==0)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
{
// finack, answer with ack
make_tcp_ack_from_any(buf);
}
// just an ack with no data, wait for next packet
continue;
}
if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0)
{
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
}
else
{
// Web Code
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<p>PLANETCAST MEDIA SERVICES LTD</p>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<body>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"text\" id=\"myurl\" name=\"url\" placeholder=\"Enter Url\"/><br>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"submit\" id=\"clickbutton\" name=\"Click Here\" />"));
plen=fill_tcp_data_p(buf,plen,PSTR("<script type=\"text/javascript\">"));
plen=fill_tcp_data_p(buf,plen,PSTR("document.getElementById(\"clickbutton\").onclick = function(){"));
plen=fill_tcp_data_p(buf,plen,PSTR("var url = document.getElementById(\"myurl\").value;"));
plen=fill_tcp_data_p(buf,plen,PSTR("location.href=url;"));
plen=fill_tcp_data_p(buf,plen,PSTR("};"));
plen=fill_tcp_data_p(buf,plen,PSTR("</script>"));
plen=fill_tcp_data_p(buf,plen,PSTR("</body"));
}
make_tcp_ack_from_any(buf); // send ack for http get
make_tcp_ack_with_data(buf,plen); // send data
continue;
}
}
// udp interface:
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V)
{
payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
// the received command has to start with t and be 4 char long
// e.g "test\0"
if (buf[UDP_DATA_P]=='t' && payloadlen==5)
{
make_udp_reply_from_request(buf,"hello",6,MYUDPPORT);
}
}
}
return (0);
}
ISR(TIMER1_CAPT_vect)
{
//do something
}
Now when I run my code , I got no webpage on my browser. So, I comment out sei() function. After this my code works fine. So, I check SPI settings in enc28j60.c. As per my knowledge SPI is not running on interrupt , so it shouldn't be affected by sei(). Here is my SPi settings in enc28j60.c:-
#define ENC28J60_CONTROL_PORT PORTB
#define ENC28J60_CONTROL_DDR DDRB
#define ENC28J60_CONTROL_CS 2
#define ENC28J60_CONTROL_SO 4
#define ENC28J60_CONTROL_SI 3
#define ENC28J60_CONTROL_SCK 5
void enc28j60Init(uint8_t* macaddr)
{
// initialize I/O
// ss as output:
ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_CS;
CSPASSIVE; // ss=0
//
ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_SI | 1<<ENC28J60_CONTROL_SCK; // mosi, sck output
cbi(ENC28J60_CONTROL_DDR,ENC28J60_CONTROL_SO); // MISO is input
//
cbi(ENC28J60_CONTROL_PORT,ENC28J60_CONTROL_SI); // MOSI low
cbi(ENC28J60_CONTROL_PORT,ENC28J60_CONTROL_SCK); // SCK low
So, can anyone tell me why my SPI mode is geting effected by sei() function and how get rid of this.
I have not read all your code but i think you are all time in interrupt. In normal mode the timer are not reset when it reach the top. Try with TCNT1 = 0; in the ISR.

Trouble with Sending HTTP 1.1 GET request

I am trying to use PubNub to publish a message to a channel but I always get "Connection Failed!".
I know the structure of a publish URL is the following:
http://pubsub.pubnub.com/publish/<PUB-KEY>/<SUB-KEY>/0/<CHANNEL>/0/%22<MESSAGE>%22
I have tested the URL on Google Chrome and it works just fine.
The following is a C flavored code is running on an Arduino UNO + Adafruit HUZZAH CC3000 WIFI Breakout. This is not an Arduino hardware question per se, because I believe there is nothing wrong with my circuit. My issue is with the structure of the HTTP GET request created using Adafruit CC3000 Library.
I am having to go with sending a GET rather than using PubNub Arduino Library because it doesn't seem to support CC3000 WIFI module. They have a JSON WIFI and Ethernet examples but both do not communicate with the CC3000 WIFI module.
char PUBKEY[] = "XXXXXXX";
char SUBKEY[] = "XXXXXXX";
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
if (client.connected())
{
client.print("GET /publish/");
client.print(PUBKEY);
client.print("/");
client.print(SUBKEY);
client.print("/0/");
client.print("MyPubChannel"); // Channel Name
client.print("/0/%22");
client.print("Hello World from Arduino!"); // Msg to publish
client.print("%22");
client.println(" HTTP/1.1");
client.print("Host: ");
client.println("pubsub.pubnub.com");
client.println();
}
else
{
Serial.println(F("Connection failed"));
}
I have read this page and understood that a correct GET request would be of the form:
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.w3.org
I am pretty sure there is something wrong with my GET request. Can anyone look at this and provide ANY hints as to what could be going wrong?
I am finally able to connect to PubNub using the code below.
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
#define WLAN_SSID "XXXWifi"
#define WLAN_PASS "XXX"
#define WLAN_SECURITY WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS 3
uint32_t ip;
// PubNub Setup
#define WEBSITE "pubsub.pubnub.com"
#define WEBPAGE "/publish/"
char PUBKEY[] = "pub-XXXX";
char SUBKEY[] = "sub-XXXX";
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER); // you can change this clock speed
Adafruit_CC3000_Client www;
void setup(void)
{
Serial.begin(115200);
/* Initialize the module */
Serial.print(F("\n Initializing WIFI Adapter..."));
if (!cc3000.begin())
{
Serial.println(F("Couldn't begin()! Check your wiring?"));
while(1);
}
Serial.print(F("Ready!\n"));
Serial.print(F("Connecting to [")); Serial.print(WLAN_SSID);
Serial.print(F("]..."));
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.print(F("Connected!\n"));
//Wait for DHCP to complete
Serial.print(F("Waiting for DHCP..."));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
Serial.print(F("Done!\n"));
Serial.print(F("Resolving PubNub..."));
ip = 0;
// Try looking up the website's IP address
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
Serial.print(F("Resolved!\n"));
www = cc3000.connectTCP(ip, 80);
for(int i=0;i<=50;i++)
{
char buffer[4];
dtostrf(i, 4, 0, buffer);
Publish("ch2", buffer);
}
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time your try to connect ... */
Serial.println(F("\n\nDisconnecting"));
www.close();
cc3000.disconnect();
}
void loop(void)
{
delay(1000);
}
void Publish(char* CH, char* MSG)
{
if (www.connected()) {
www.fastrprint(F("GET "));
www.fastrprint(WEBPAGE);
www.fastrprint(PUBKEY);
www.fastrprint(F("/"));
www.fastrprint(SUBKEY);
www.fastrprint(F("/0/"));
www.fastrprint(CH);
www.fastrprint(F("/0/%22"));
www.fastrprint(MSG);
www.fastrprint(F("%22"));
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: "));
www.fastrprint(WEBSITE);
www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return;
}
//Read data until either the connection is closed, or the idle timeout is reached.
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
//Serial.print(c);
lastRead = millis();
}
}
}
char* clean(char* MSG)
{
return MSG;
}