At the moment of time I had a raspberry Pi arrived from China and really wanted to put my hands on it.
Initially I installed the Raspbian linux on it, but ironically enough I struggled with Chinese memory card a lot and all resolved when I finally bought the well-known in the store.
So what I wanted to do: my adsl modem which I had got for free had some freezes which fixed after the reboot. With time it evolved to each day couple reboots routine.
Solution in mind: to ping some known website one time per n minutes, and, if it is not – make a reboot.
That fact that my PRi stands next to the modem was also in favor of the solution.
Initially, I even thought that I could use the supply from the modem for RPi, but then decided that it doesn’t look nice and practical.
So, we would need to gain the input-output ports control somehow. I used to code in C, so the most convenient tool in C what I found was wiringPi.
This website has quite good theory descriptions and examples of work, just I was puzzled by their pinout:
that’s all we need, we need to compile your new source and launch it from root:
gcc -Wall -o execfilename cfilename.c -lwiringPi sudo ./execfiname
OK, now we know how to control IO, now lets do the website checker. After some websearch I mad a conclusion that function “popen” suits me best. This function allow to call linux commands from the code:
#include <stdio.h> #include "/usr/include/string.h" #include "/usr/include/stdlib.h" int main () { FILE *cmd = popen ( "ping -c 4 google.com", "r" ); //ping ya.ru 4 раза char *s = malloc ( sizeof ( char ) * 200 ); while ( 1 ) { fgets ( s, sizeof ( char )*200, cmd ); printf ( "%s", s);//show outcome if ( strstr ( s, "icmp_rec" ) != 0 ) //проверяем есть ли нужная инфа break; } pclose ( cmd ); return 0; }
That was easy, now a bit of the hardware.
Also quite easy, a transistor which controls the relay which controls the power 🙂
I also added the software watchdog with the 60s period, if it reached one minute and has not been reseted, then we have a frozen program and we need to reset. To work with timers I used the dev/time.h library.
For instance, let me try to ping non-existing website and if we wont be able to reach the response for 5 seconds, we are gonna to reset our mode.
#include <stdio.h> #include "/usr/include/string.h" #include "/usr/include/stdlib.h" #include <sys/time.h> #include <wiringPi.h> int main () { wiringPiSetup(); //Init wiringPi pinMode (0, OUTPUT); //GPIO 0 на выход digitalWrite (0, LOW); //и в 0 его сразу double t1, t2; unsigned char flag = 0; struct timeval tim; gettimeofday(&tim, NULL); t1=tim.tv_sec+(tim.tv_usec/1000000.0); //Время старта в секундах FILE *cmd = popen ( "ping -c 4 razdvatridvaodin.com", "r" ); char *s = malloc ( sizeof ( char ) * 200 ); do { fgets ( s, sizeof ( char )*200, cmd ); printf ( "%s", s);//show outcome gettimeofday(&tim, NULL); t2 = tim.tv_sec+(tim.tv_usec/1000000.0); //Текущее время работы в секундах if ( strstr ( s, "ms" ) != 0 ) //проверяем допинговались ли мы куда-нибудь вообще, если да то прерываем цикл { flag = 1; break; } }while((t2-t1)<5); //Если висим слишком долго то пора делать ребут if (!flag) //Обрабатываем отсутствие коннекта { digitalWrite (0, HIGH); delay(1000); delay(1000); digitalWrite (0, LOW); } pclose ( cmd ); return 0; }
a result:
Works!
The final code:
#include <stdio.h> #include "/usr/include/string.h" #include "/usr/include/stdlib.h" #include <sys/time.h> #include <wiringPi.h> int main () { wiringPiSetup(); //Init wiringPi pinMode (0, OUTPUT); //0 пин на выход digitalWrite (0, LOW); //пока не трогаем его double t1, t2; unsigned char flag = 0; struct timeval tim; gettimeofday(&tim, NULL); t1=tim.tv_sec+(tim.tv_usec/1000000.0); //Время старта в секундах FILE *cmd = popen ( "ping -c 4 google.com", "r" ); //ping google.com 4 раза char *s = malloc ( sizeof ( char ) * 200 ); do { fgets ( s, sizeof ( char )*200, cmd ); printf ( "%s", s);//show outcome gettimeofday(&tim, NULL); t2 = tim.tv_sec+(tim.tv_usec/1000000.0); //Текущее время работы в секундах if ( strstr ( s, "ms" ) != 0 ) //проверяем допинговались ли мы куда-нибудь вообще, если да то прерываем цикл { flag = 1; //устанавливаем флаг break; //выходим из цикла } }while((t2-t1)<60); //Если висим слишком долго то пора делать ребут if (!flag) //Обрабатываем отсутствие коннекта { digitalWrite (0, HIGH); delay(1000); delay(1000); digitalWrite (0, LOW); } pclose ( cmd ); return 0; }
Great, we have some code, which even works, now we need to schedule the launching of this program each n minutes. Linus usually uses cron service, the help related to this service could be found in many places and raspberry PI website one of them. And that what I would usually do, but here is the information that advanced users should not use it, not sure why, but let me pretend that I am an advanced user.
To check how it works I made a simple code which just writes a current time to the file:
#include <time.h> #include <stdio.h> int main( void ) { FILE * fp; fp = fopen ("/home/pi/Buf/file.txt", "a+"); time_t t; time(&t); fprintf( fp, "The time is %s\n", ctime( &t) ); fclose(fp); return 0; }
Compiling the code, naming it TimeIs and going to /etc/cron.d, creating a file mycronjob there with a next context:
*/1 * * * * root /home/pi/Buf/./TimeIs
Which means that the function is going to be launched each minute, checking the result:
The time is Sun Jul 20 18:38:01 2014 The time is Sun Jul 20 18:39:02 2014 The time is Sun Jul 20 18:40:01 2014 The time is Sun Jul 20 18:41:01 2014 The time is Sun Jul 20 18:42:01 2014 The time is Sun Jul 20 18:43:01 2014
At this moment of time I decided that I also need to have logs:
if (!flag) //Обрабатываем отсутствие коннекта { digitalWrite (0, HIGH); delay(1000); delay(1000); digitalWrite (0, LOW); fprintf( fp, "Test of connection failed at %s\n", ctime( &t) ); } else fprintf( fp, "Test of connection passed at %s\n", ctime( &t) );
Settled the cron time to be 10 min and we are ready. Here also some messy photos of the hardware: