Go Down

Topic: 'StrContains' was not declared in this scope ??? (Read 3933 times) previous topic - next topic

zainb

Hoi,

Kan iemand mij helpen met deze foutmelding, kom er echt niet uit. Code onderstaand


Alvast bedankt



Code: [Select]
#include <spi.h>
#include <ethernet.h>
#include <sd.h>
// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ 60

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
File webFile; // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
boolean LED_state[2] = {0}; // stores the states of the LEDs

void setup()
{
// disable Ethernet chip
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

Serial.begin(9600); // for debugging

// initialize SD card
Serial.println("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("ERROR - SD card initialization failed!");
return; // init failed
}
Serial.println("SUCCESS - SD card initialized.");
// check for index.htm file
if (!SD.exists("index.htm")) {
Serial.println("ERROR - Can't find index.htm file!");
return; // can't find index file
}
Serial.println("SUCCESS - Found index.htm file.");
// switches
pinMode(2, INPUT);
pinMode(3, INPUT);
// LEDs
pinMode(9, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);

Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
}

void loop()
{
EthernetClient client = server.available(); // try to get client

if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
// limit the size of the stored received HTTP request
// buffer first part of HTTP request in HTTP_req array (string)
// leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
// remainder of header follows below, depending on if
// web page or XML page is requested
// Ajax request - send XML file
if (StrContains(HTTP_req, "ajax_inputs")) {
// send rest of HTTP header
client.println("Content-Type: text/xml");
client.println("Connection: keep-alive");
client.println();
SetLEDs();
// send XML file containing input states
XML_response(client);
}
else { // web page request
// send rest of HTTP header
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println();
// send web page
webFile = SD.open("index.htm"); // open web page file
if (webFile) {
while(webFile.available()) {
client.write(webFile.read()); // send web page to client
}
webFile.close();
}
}
// display received HTTP request on serial port
Serial.print(HTTP_req);
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)

// read buttons and debounce
ButtonDebounce();
}

// function reads the push button switch states, debounces and latches the LED states
// toggles the LED states on each push - release cycle
// hard coded to debounce two switches on pins 2 and 3; and two LEDs on pins 6 and 7
// function adapted from Arduino IDE built-in example:
// File --> Examples --> 02.Digital --> Debounce

void ButtonDebounce(void)
{
static byte buttonState[2] = {LOW, LOW}; // the current reading from the input pin
static byte lastButtonState[2] = {LOW, LOW}; // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
static long lastDebounceTime[2] = {0}; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers

byte reading[2];

reading[0] = digitalRead(2);
reading[1] = digitalRead(3);

for (int i = 0; i < 2; i++) {
if (reading[i] != lastButtonState[i]) {
// reset the debouncing timer
lastDebounceTime[i] = millis();
}

if ((millis() - lastDebounceTime[i]) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:

// if the button state has changed:
if (reading[i] != buttonState[i]) {
buttonState[i] = reading[i];

// only toggle the LED if the new button state is HIGH
if (buttonState[i] == HIGH) {
LED_state[i] = !LED_state[i];
}
}
}
} // end for() loop

// set the LEDs
digitalWrite(9, LED_state[0]);
digitalWrite(5, LED_state[1]);
digitalWrite(6, LED_state[2]);
digitalWrite(7, LED_state[3]);
digitalWrite(8, LED_state[4]);

// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonState[0] = reading[0];
lastButtonState[1] = reading[1];
}

// checks if received HTTP request is switching on/off LEDs
// also saves the state of the LEDs
void SetLEDs(void)
{
// Main Verlichting (pin 9)
if (StrContains(HTTP_req, "LED1=1")) {
LED_state[0] = 1; // save LED state
digitalWrite(9, HIGH);
}
else if (StrContains(HTTP_req, "LED1=0")) {
LED_state[0] = 0; // save LED state
digitalWrite(9, LOW);
}
// Sub Verlichting (pin 5)
if (StrContains(HTTP_req, "LED2=1")) {
LED_state[1] = 1; // save LED state
digitalWrite(5, HIGH);
}
else if (StrContains(HTTP_req, "LED2=0")) {
LED_state[1] = 0; // save LED state
digitalWrite(5, LOW);
}
// Alarm (pin 6)
if (StrContains(HTTP_req, "LED3=1")) {
LED_state[2] = 1; // save LED state
digitalWrite(6, HIGH);
}
else if (StrContains(HTTP_req, "LED3=0")) {
LED_state[2] = 0; // save LED state
digitalWrite(6, LOW);
}

// Rolluik 1(pin 7)
if (StrContains(HTTP_req, "LED4=1")) {
LED_state[3] = 1; // save LED state
digitalWrite(7, HIGH);
}
else if (StrContains(HTTP_req, "LED4=0")) {
LED_state[3] = 0; // save LED state
digitalWrite(7, LOW);
}
// Rolluik 2 (pin 8)
if (StrContains(HTTP_req, "LED5=1")) {
LED_state[4] = 1; // save LED state
digitalWrite(8, HIGH);
}
else if (StrContains(HTTP_req, "LED5=0")) {
LED_state[4] = 0; // save LED state
digitalWrite(8, LOW);
}
}

// send the XML file with analog values, switch status
// and LED status
void XML_response(EthernetClient cl)
{
int analog_val; // stores value read from analog inputs
int count; // used by 'for' loops
int sw_arr[] = {2, 3}; // pins interfaced to switches

cl.print("");
cl.print("<inputs>");
// checkbox LED states
// LED1
cl.print("<led>");
if (LED_state[0]) {
cl.print("checked");
}
else {
cl.print("unchecked");
}
cl.println("</led>");
// button LED states
// LED2
cl.print("<led>");
if (LED_state[1]) {
cl.print("on");
}
else {
cl.print("off");
}
cl.println("</led>");
cl.print("</inputs>");
}

// button LED states
// LED3
cl.print("<led>");
if (LED_state[2]) {
cl.print("on");
}
else {
cl.print("off");
}
cl.println("</led>");
cl.print("</inputs>");
}

// button LED states
// LED4
cl.print("<led>");
if (LED_state[3]) {
cl.print("on");
}
else {
cl.print("off");
}
cl.println("</led>");
cl.print("</inputs>");
}

// button LED states
// LED5
cl.print("<led>");
if (LED_state[4]) {
cl.print("on");
}
else {
cl.print("off");
}
cl.println("</led>");
cl.print("</inputs>");
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
for (int i = 0; i < length; i++) {
str[i] = 0;
}
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
char found = 0;
char index = 0;
char len;

len = strlen(str);

if (strlen(sfind) > len) {
return 0;
}
while (index < len) {
if (str[index] == sfind[found]) {
found++;
if (strlen(sfind) == found) {
return 1;
}
}
else {
found = 0;
}
index++;
}

return 0;
}

shooter

betekent meestal dat je een library niet laadt, of niet hebt.
kijkeven verder in de foutmeldingen, en heel normaal hoor, als je een programma kopieert, dan snap je niet hoe het werkt, en zit je vaak in de ellende.
paul deelen
shooter@home.nl
making controls with codesys PLC and arduino

zainb

Ja ik heb hem gekopieerd en gewijzigd.
Dit is de originele maar ik heb er een paar 'LEDS' aan toegevoegd en dan werkt hij opeens niet meer

Code kan ik hier niet plaatsen omdat het de 9000 characters overschrijdt,
maar dit is de link http://startingelectronics.org/articles/arduino/switch-and-web-page-button-LED-control/


nicoverduin

Die paar 'LEDS' dis hje hebt toegevoegd zijn juist de oorzaak van jouw problemen. Je hebt veel te veel sluit accolades waardoor het programma in feite al is afgesloten terwijl er nog code komt. Als je nu eens de toets combinatie CTRL-T gebruikt gaat de IDE jouw code weer eens goed indelen. Daar waar het ophoudt (dus bij LED3) zit daarboven een sluit accolade. Dat is niet goed. En er zitten er nog meer van die fouten in.
Dit heeft niets met libraries te maken. De boodschap die je krijgt komt omdat die functie helemaal onderaan staat. Maar ja voor de compiler was het programma allang afgesloten en zie hij die functie niet meer. 
Dus HEEL VAAK CTRL-T gebruiken. Ga je gelijk netter programmeren.
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

zainb

Thnx, dit heb ik gebruikt.. geen effect.
Heb zojuist een kwartier alle accolades proberen te checken maar ik kom er nog steeds niet uit. In welk deel staan er dan teveel?

Heb het nu zo aangepast dat alleen maar de laatste een error geeft, pin 8

Volgens mij ligt het niet bij void setleds
Als ik deze code erin plak van een andere sketch waar hij wel werkt met hetzelfde aantal LED'S geeft hij ook een error aan
Code: [Select]
void SetLEDs(void)
{
 // LED 1 (pin 6)
 if (StrContains(HTTP_req, "LED1=1")) {
   LED_state[0] = 1;  // save LED state
   digitalWrite(6, HIGH);
 }
 else if (StrContains(HTTP_req, "LED1=0")) {
   LED_state[0] = 0;  // save LED state
   digitalWrite(6, LOW);
 }
 // LED 2 (pin 7)
 if (StrContains(HTTP_req, "LED2=1")) {
   LED_state[1] = 1;  // save LED state
   digitalWrite(7, HIGH);
 }
 else if (StrContains(HTTP_req, "LED2=0")) {
   LED_state[1] = 0;  // save LED state
   digitalWrite(7, LOW);
 }
 // LED 3 (pin 8)
 if (StrContains(HTTP_req, "LED3=1")) {
   LED_state[2] = 1;  // save LED state
   digitalWrite(8, HIGH);
 }
 else if (StrContains(HTTP_req, "LED3=0")) {
   LED_state[2] = 0;  // save LED state
   digitalWrite(8, LOW);
 }

 // LED 4 (pin 9)
 if (StrContains(HTTP_req, "LED4=1")) {
   LED_state[3] = 1;  // save LED state
   digitalWrite(9, HIGH);
 }
 else if (StrContains(HTTP_req, "LED4=0")) {
   LED_state[3] = 0;  // save LED state
   digitalWrite(9, LOW);
 }

 // LED 4 (pin 9)
 if (StrContains(HTTP_req, "LED4=1")) {
   LED_state[3] = 1;  // save LED state
   digitalWrite(9, HIGH);
 }
 else if (StrContains(HTTP_req, "LED4=0")) {
   LED_state[3] = 0;  // save LED state
   digitalWrite(9, LOW);
 }
 // LED 4 (pin 9)
 if (StrContains(HTTP_req, "LED4=1")) {
   LED_state[3] = 1;  // save LED state
   digitalWrite(9, HIGH);
 }
 else if (StrContains(HTTP_req, "LED4=0")) {
   LED_state[3] = 0;  // save LED state
   digitalWrite(9, LOW);
 }
}[code/]

MAS3

Als je met de IDE de cursor net naast een { accolade zet, dan word er om de bijbehorende (of tenminste wat de IDE als de bijbehorende } accolade een klein blauw rechthoekje gezet (en vice versa).
Op die manier kun je controleren of je nog goed gaat met die accolades.
Je moet niet alleen kijken of je aantal accolades correct zijn, maar ook of ze op de juiste plaats staan.

Want als je dit doet:
Code: [Select]

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

{
// dit is allemaal gebakken lucht
}


Dan zal blijken dat gebakken lucht niets waard is.
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

nicoverduin

Als je CTRL-T gebruikt gaat hij je code opnieuw opmaken met het juist inspringen. Bij LED3 stop hij daar mee. Oorzaak? omdat je daarboven een sluit accolade die daar niet thuis hoort. Als je dan weer CTLR-T doet... Dan stop hij wat verder. Nl. Bij LED4 enz enz.
En dan ge ja net zolang door tot je het hebt opgelost. En het kan want ik heb de code hier gewoon kunnen compileren. Dus niet komen met "geen effect". Dan heb jij nog meer van dit soort fouten. Hoeveel? ga ik je niet vertellen omdat ik vind dat je te snel opgeeft. En dit heeft alles te maken met zorgvuldigheid. Essentieel bij programmeren.....
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

nicoverduin

Thnx, dit heb ik gebruikt.. geen effect.
Heb zojuist een kwartier alle accolades proberen te checken maar ik kom er nog steeds niet uit. In welk deel staan er dan teveel?

Heb het nu zo aangepast dat alleen maar de laatste een error geeft, pin 8

Volgens mij ligt het niet bij void setleds
Als ik deze code erin plak van een andere sketch waar hij wel werkt met hetzelfde aantal LED'S geeft hij ook een error aan
Code: [Select]
void SetLEDs(void)
{
 // LED 1 (pin 6)
 if (StrContains(HTTP_req, "LED1=1")) {
   LED_state[0] = 1;  // save LED state
   digitalWrite(6, HIGH);
 }
 else if (StrContains(HTTP_req, "LED1=0")) {
   LED_state[0] = 0;  // save LED state
   digitalWrite(6, LOW);
 }
 // LED 2 (pin 7)
 if (StrContains(HTTP_req, "LED2=1")) {
   LED_state[1] = 1;  // save LED state
   digitalWrite(7, HIGH);
 }
 else if (StrContains(HTTP_req, "LED2=0")) {
   LED_state[1] = 0;  // save LED state
   digitalWrite(7, LOW);
 }
 // LED 3 (pin 8)
 if (StrContains(HTTP_req, "LED3=1")) {
   LED_state[2] = 1;  // save LED state
   digitalWrite(8, HIGH);
 }
 else if (StrContains(HTTP_req, "LED3=0")) {
   LED_state[2] = 0;  // save LED state
   digitalWrite(8, LOW);
 }

 // LED 4 (pin 9)
 if (StrContains(HTTP_req, "LED4=1")) {
   LED_state[3] = 1;  // save LED state
   digitalWrite(9, HIGH);
 }
 else if (StrContains(HTTP_req, "LED4=0")) {
   LED_state[3] = 0;  // save LED state
   digitalWrite(9, LOW);
 }

 // LED 4 (pin 9)
 if (StrContains(HTTP_req, "LED4=1")) {
   LED_state[3] = 1;  // save LED state
   digitalWrite(9, HIGH);
 }
 else if (StrContains(HTTP_req, "LED4=0")) {
   LED_state[3] = 0;  // save LED state
   digitalWrite(9, LOW);
 }
 // LED 4 (pin 9)
 if (StrContains(HTTP_req, "LED4=1")) {
   LED_state[3] = 1;  // save LED state
   digitalWrite(9, HIGH);
 }
 else if (StrContains(HTTP_req, "LED4=0")) {
   LED_state[3] = 0;  // save LED state
   digitalWrite(9, LOW);
 }
}[code/]

Als je nu eens gewoon doet wat je verteld is, dan had je alles al draaien......
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

zainb

Als je met de IDE de cursor net naast een { accolade zet, dan word er om de bijbehorende (of tenminste wat de IDE als de bijbehorende } accolade een klein blauw rechthoekje gezet (en vice versa).
Op die manier kun je controleren of je nog goed gaat met die accolades.
Je moet niet alleen kijken of je aantal accolades correct zijn, maar ook of ze op de juiste plaats staan.

Want als je dit doet:
Code: [Select]

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

{
// dit is allemaal gebakken lucht
}


Dan zal blijken dat gebakken lucht niets waard is.

Dit heb ik al gedaan, de hele sketch.


@nicoverduin hij geeft aan; no changes necessary for auto format??

nicoverduin

Als je met de IDE de cursor net naast een { accolade zet, dan word er om de bijbehorende (of tenminste wat de IDE als de bijbehorende } accolade een klein blauw rechthoekje gezet (en vice versa).
Op die manier kun je controleren of je nog goed gaat met die accolades.
Je moet niet alleen kijken of je aantal accolades correct zijn, maar ook of ze op de juiste plaats staan.

Want als je dit doet:
Code: [Select]

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

{
// dit is allemaal gebakken lucht
}


Dan zal blijken dat gebakken lucht niets waard is.

Ach het is nog veel eenvoudiger... Lang leve de copy paste acties zonder verder te kijken..... De software engineer van de toekomst?
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

nicoverduin

Dit heb ik al gedaan, de hele sketch.


@nicoverduin hij geeft aan; no changes necessary for auto format??
Dan heb je met al jou wijsheid je code mogelijk verknalt. Want ik paste de wijzigingen toe zoals ik gelijk heb gezegd en het ging als een tierelier. En als je de code hebt verknalt dan is het bekende gebeuren... terug gaan naar de backup... en heb je die niet... dan heb je mazzel, want het source heb je zelf hier geplaatst. En dan begin je weer opnieuw en let je beter op. Samenvattend, Het zijn een aantal accolades die weg moeten en ze zijn nog consequent ook agv. klakkeloos kopieren. en CTRL-T is de oplossing.
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

zainb

De tip van MAS3 heb ik al gedaan, heb heel het document zelfs nagekeken.
En met control T krijg ik no changes necessary?
Wat doe ik fout?

Ik had die code alleen maar even geplakt om te testen, daarna gelijk weer teruggezet naar het oude waar ik mee begon  :)

nicoverduin

Ik heb je net verteld welke code je moet gebruiken. Dus gewoon opnieuw beginnen. Ik deed net niet anders. opstarten IDE, laad jouw volledige programma en wat keren CTRL-T. Dus verdere discussie hierover is zinloos. 
En wat je fout doet.....vul dat zelf maar in. Het is je nu een paar keer verteld.
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

sterretje

#13
Jun 30, 2016, 02:26 pm Last Edit: Jun 30, 2016, 02:28 pm by sterretje
De tip van MAS3 heb ik al gedaan, heb heel het document zelfs nagekeken.
En met control T krijg ik no changes necessary?
Wat doe ik fout?

Ik had die code alleen maar even geplakt om te testen, daarna gelijk weer teruggezet naar het oude waar ik mee begon  :)
Dit is een stukje van je originele code na een auto format
Code: [Select]

void XML_response(EthernetClient cl)
{
  ...
  ...
} <------- dit is regel 264

// button LED states
// LED3
cl.print("<led>");

Je kunt direkt zien dat er iets fout is omdat de functie aanroep in regel 268 begint op het begin van de regel.

De accolade op regel 264 sluit the functie XML_response af. Haal die accolade weg (zoals Nico zegt). Gebruik daarna <ctrl>T; gegarandeerd dat je dan de melding "Auto Format finished" krijgt. Maar belangrijker is dat daarna de functie aanroep op regel 267 ingesprongen is.

Loop verder door je code; hetzelfde probleem in regel 277. Repareer en <ctrl>T.

Totdat alles correct inspringt.

PS
Dit is in essentie een andere bewoording van wat Nico al gezegd heeft; ik hoop dat een ander bewoording het op een andere manier duidelijk maakt wat je moet doen.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

nicoverduin

Dit is een stukje van je originele code na een auto format
Code: [Select]

void XML_response(EthernetClient cl)
{
  ...
  ...
} <------- dit is regel 264

// button LED states
// LED3
cl.print("<led>");

Je kunt direkt zien dat er iets fout is omdat de functie aanroep in regel 268 begint op het begin van de regel.

De accolade op regel 264 sluit the functie XML_response af. Haal die accolade weg (zoals Nico zegt). Gebruik daarna <ctrl>T; gegarandeerd dat je dan de melding "Auto Format finished" krijgt. Maar belangrijker is dat daarna de functie aanroep op regel 267 ingesprongen is.

Loop verder door je code; hetzelfde probleem in regel 277. Repareer en <ctrl>T.

Totdat alles correct inspringt.

PS
Dit is in essentie een andere bewoording van wat Nico al gezegd heeft; ik hoop dat een ander bewoording het op een andere manier duidelijk maakt wat je moet doen.
Ik had gehoopt dat je dit dus niet had gedaan. De TS leert weer njente nada en komt over een paar maanden met dezelfde vragen. Ik had ook de uitkomst wel kunnen geven. Ik had het immers al opgelost. De essentie was dat de TS zich realiseert dat klakkeloos plakken van code zorgvuldigheid vereist. Dus even nadenken voordat je wat doet. De IDE van de arduino (hoe primitief ook) heeft een aantal hulpmiddelen die de gebruiker ter beschikking staan. De meesten gebruikers beperken zich tot het aanklikken van het vinkje en upload pijltje... En komen dan met vragen die te wijten zijn aan slordigheid (en luiheid?). Als wij alles voor ze oplossen blijf je aan de gang. 
Die tutorials doen de meesten al niet. Want er zijn nooit vragen over de tutorials. Dat iemand iets niet begrijpt snap ik, maar als je het uitlegt en hij doet wat anders... En je legt het nog een keer uit... Dan kan het goed zijn om hem even in zijn eigen sop gaar te laten koken. De oplossing is appeltje eitje maar nu leert hij niets... Dus over een paar maanden (of eerder komt ie weer)...
Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

Go Up