๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[๋ฆฌ๋ ์ค ๋คํธ์ํฌ ํ๋ก๊ทธ๋๋ฐ] ์น ์๋ฒ์ ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด์ ์ ์ด ๋ณธ๋ฌธ
[๋ฆฌ๋ ์ค ๋คํธ์ํฌ ํ๋ก๊ทธ๋๋ฐ] ์น ์๋ฒ์ ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด์ ์ ์ด
์ง์ง์ํ์นด 2024. 2. 13. 00:15<์์์ง ๋์ ์ฌ๋ฌผ์ธํฐ๋ท์ ์ํ ๋ฆฌ๋ ์ค ํ๋ก๊ทธ๋๋ฐ with ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ์์ ์ ์ฐธ๊ณ ํด์ ์์ฑํ์์ต๋๋ค :-)>
โญ ์น ์๋ฒ์ ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด์ ์ ์ด
HTML ๋ฌธ์ ์์ ์จ๋์ ์ต๋ ๋ฑ์ ์ง์ ํ์ํ ์ ์๋๋ก ์ฝ์
ํจ + lED ์ผ๊ณ ๋ ์ ์๋ ๋ผ๋์ค ๋ฒํผ + ์์
์ ์ฐ์ฃผํ๊ณ ๋ชจํฐ๋ฅผ ์ ์ด
์น ๋ธ๋ผ์ฐ์ ์์ ์น ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ๋ <FORM> ํ๊ทธ๋ฅผ ์ฌ์ฉํ๋ค
<FORM> ํ๊ทธ๋ POST ๋ฉ์์ง๋ก ์์ฒญ์ ๋ณด๋ด์ง๋ง, ์ ์น ์๋ฒ๋ GET ๋ฉ์๋๋ง ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์
<FORM> ํ๊ทธ์ method ์์ฑ์ ์ด์ฉํ์ฌ GET ๋ฉ์๋๋ก ๋ณด๋ด๋๋ก ์ค์ ํ๋ค
์น ๋ธ๋ผ์ฐ์ ์์ ์น ํ์ด์ง๋ฅผ ๋ถ๋ฌ๋ค์ฌ์ ์ต์
์ ์ ํํ๊ณ Submit ๋ฒํผ์ ์ ํํ๋ฉด, ์น ์๋ฒ๋ก
'http://์๋ฒ์ฃผ์:ํฌํธ๋ฒํธ/index.html?led=Off' ์์ฒญ์ GET ๋ฉ์๋๋ก ์ ๋ฌ๋๋ค
์น ์๋ฒ์์๋ GET ๋ฉ์๋๋ก ์ ์ก๋ ๋ฉ์์ง๋ฅผ ๋ถ์ํ๊ณ ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด์ GPIO ์ ํด๋น ๋ช
๋ น์ ๋ด๋ฆด ์ ์๋ค
์ฝ๋๋ฅผ ๋น๋ ์ Pthread ๋ผ์ด๋ธ๋ฌ๋ฆฌ, wiringPi ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋ ๋งํฌํด์ผ ํ๋ค
์ฐ๋๋ ์จ์ต๋ ์ธก์ ์ผ์๊ฐ ์์ด์ ์๋ํ์ง ์๋๋ค ใ
// rpi6.c
// PC ์์ ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด๋ฅผ ์ ์ดํ ์ ์๋ ์ฝ๋
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <termios.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <linux/input.h>
static const char* I2C_DEV = "/dev/i2c-1"; /* I2C๋ฅผ ์ํ ์ฅ์น ํ์ผ */
static const int I2C_SLAVE = 0x0703; /* ioctl() ํจ์์์ I2C_SLAVE ์ค์ ์ ์ํ ๊ฐ */
static const int LPS25H_ID = 0x5C; /* SenseHAT์ I2C-1์ ๊ฐ */
static const int HTS221_ID = 0x5F;
static const int CTRL_REG1 = 0x20; /* STMicroelectronics์ ์คํ ๋ฌธ์์ ๊ฐ */
static const int CTRL_REG2 = 0x21;
static const int PRESS_OUT_XL = 0x28; /* STMicroelectronics์ LPS25H ์คํ ๋ฌธ์์ ๊ฐ */
static const int PRESS_OUT_L = 0x29;
static const int PRESS_OUT_H = 0x2A;
static const int PTEMP_OUT_L = 0x2B;
static const int PTEMP_OUT_H = 0x2C;
static const int H0_T0_OUT_L = 0x36; /* STMicroelectronics์ HTS221 ์คํ ๋ฌธ์์ ๊ฐ */
static const int H0_T0_OUT_H = 0x37;
static const int H1_T0_OUT_L = 0x3A;
static const int H1_T0_OUT_H = 0x3B;
static const int H0_rH_x2 = 0x30;
static const int H1_rH_x2 = 0x31;
static const int H_T_OUT_L = 0x28;
static const int H_T_OUT_H = 0x29;
static const int T0_OUT_L = 0x3C;
static const int T0_OUT_H = 0x3D;
static const int T1_OUT_L = 0x3E;
static const int T1_OUT_H = 0x3F;
static const int T0_degC_x8 = 0x32;
static const int T1_degC_x8 = 0x33;
static const int T1_T0_MSB = 0x35;
static const int TEMP_OUT_L = 0x2A;
static const int TEMP_OUT_H = 0x2B;
/* ์ค๋ ๋์์ ์ฌ์ฉํ๋ ๋ฎคํ
์ค */
static pthread_mutex_t pressure_lock;
static pthread_mutex_t temperature_lock;
static int is_run = 1; /* ์ค๋ ๋ ์ข
๋ฃ๋ฅผ ์ํ ํ๋๊ทธ */
int pressure_fd, temperature_fd;
int kbhit(void);
/* ์ค๋ ๋ ์ฒ๋ฆฌ๋ฅผ ์ํ ํจ์ */
void* webserverFunction(void* arg);
static void *clnt_connection(void *arg);
int sendData(FILE* fp, char *ct, char *filename);
void sendOk(FILE* fp);
void sendError(FILE* fp);
void getPressure(int fd, double *temperature, double *pressure); /* ๊ธฐ์๊ณผ ์จ๋๋ฅผ ์ํ ํจ์ */
void getTemperature(int fd, double *temperature, double *humidity); /* ์จ๋์ ์ต๋๋ฅผ ์ํ ํจ์ */
void *pressureFunction(void *arg)
{
double t_c = 0.0; /* ์จ๋์ ์๋ ฅ์ ์ถ๋ ฅํ๊ธฐ ์ํ ๋ณ์ */
double pressure = 0.0;
while(is_run) {
if(pthread_mutex_trylock(&pressure_lock) != EBUSY) { /* ์๊ณ ๊ตฌ์ญ ์ค์ */
/* LPS25H ์ฅ์น ์ด๊ธฐํ */
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG1, 0x00);
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG1, 0x84);
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG2, 0x01);
getPressure(pressure_fd, &t_c, &pressure);
printf("Temperature(from LPS25H) = %.2fยฐC\n", t_c);
printf("Pressure = %.0f hPa\n", pressure);
pthread_mutex_unlock(&pressure_lock); /* ์๊ณ ๊ตฌ์ญ ํด์ */
}
delay(1000);
}
return NULL;
}
void *temperatureFunction(void *arg)
{
double temperature, humidity;
while(is_run) {
if(pthread_mutex_trylock(&temperature_lock) != EBUSY) { /* ์๊ณ ๊ตฌ์ญ ์ค์ */
/* HTS221 ์ฅ์น ์ด๊ธฐํ */
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG1, 0x00);
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG1, 0x84);
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG2, 0x01);
getTemperature(temperature_fd, &temperature, &humidity);
printf("Temperature(from HTS221) = %.2fยฐC\n", temperature);
printf("Humidity = %.0f%% rH\n", humidity);
pthread_mutex_unlock(&temperature_lock); /* ์๊ณ ๊ตฌ์ญ ํด์ */
}
delay(1000);
}
return NULL;
}
void* joystickFunction(void* arg)
{
int fd;
struct input_event ie;
char* joy_dev = "/dev/input/event10";
if((fd = open(joy_dev, O_RDONLY)) == -1) {
perror("opening device");
return NULL;
}
while(is_run) {
read(fd, &ie, sizeof(struct input_event));
printf("time %ld.%06ld\ttype %d\tcode %-3d\tvalue %d\n",
ie.time.tv_sec, ie.time.tv_usec, ie.type, ie.code,
ie.value);
if(ie.type) {
switch(ie.code) {
case KEY_UP: printf("Up\n"); break; /* 'Up' ๋ฐฉํฅํค: ์กฐ์ด์คํฑ 'Up' */
case KEY_DOWN: printf("Down\n"); break; /* 'Down' ๋ฐฉํฅํค: ์กฐ์ด์คํฑ 'Down' */
case KEY_LEFT: printf("Left\n"); break; /* 'Left' ๋ฐฉํฅํค: ์กฐ์ด์คํฑ 'Left' */
case KEY_RIGHT: printf("Right\n"); break; /* 'Right' ๋ฐฉํฅํค: ์กฐ์ด์คํฑ 'Right' */
case KEY_ENTER: /* โEnterโ ํค: ์กฐ์ด์คํฑ โPressโ */
printf("Enter\n"); is_run = 0; break;
default: printf("Default\n"); break; /* ์์ ํค๊ฐ ์๋ ๊ฒฝ์ฐ */
}
}
delay(100);
}
return NULL;
}
int main(int argc, char **argv)
{
int i = 0;
pthread_t ptPressure, ptTemperature, ptJoystick, ptWebserver;
pthread_mutex_init(&pressure_lock, NULL); /* ๋ฎคํ
์ค ์ด๊ธฐํ */
pthread_mutex_init(&temperature_lock, NULL);
/* ํ๋ก๊ทธ๋จ์ ์์ํ ๋ ์๋ฒ๋ฅผ ์ํ ํฌํธ ๋ฒํธ๋ฅผ ์
๋ ฅ๋ฐ๋๋ค. */
if(argc!=2) {
printf("usage: %s <port>\n", argv[0]);
return -1;
}
/* I2C ์ฅ์น ํ์ผ์ ์คํ */
if((pressure_fd = open(I2C_DEV, O_RDWR)) < 0) {
perror("Unable to open i2c device");
return 1;
}
/* I2C ์ฅ์น๋ฅผ ์ฌ๋ ์ด๋ธ(slave) ๋ชจ๋๋ก LPS25H๋ฅผ ์ค์ */
if(ioctl(pressure_fd, I2C_SLAVE, LPS25H_ID) < 0) {
perror("Unable to configure i2c slave device");
close(pressure_fd);
return 1;
}
/* I2C ์ฅ์น ํ์ผ์ ์คํ */
if((temperature_fd = open(I2C_DEV, O_RDWR)) < 0) {
perror("Unable to open i2c device");
return 1;
}
/* I2C ์ฅ์น๋ฅผ ์ฌ๋ ์ด๋ธ(slave) ๋ชจ๋๋ก HTS221๋ฅผ ์ค์ */
if(ioctl(temperature_fd, I2C_SLAVE, HTS221_ID) < 0) {
perror("Unable to configure i2c slave device");
close(temperature_fd);
return 1;
}
// pthread_create(&ptPressure, NULL, pressureFunction, NULL);
// pthread_create(&ptTemperature, NULL, temperatureFunction, NULL);
pthread_create(&ptJoystick, NULL, joystickFunction, NULL);
pthread_create(&ptWebserver, NULL, webserverFunction, (void*)(atoi(argv[1])));
printf("q : Quit\n");
for(i = 0; is_run;i++) {
if(kbhit()) { /* ํค๋ณด๋๊ฐ ๋๋ ธ๋์ง ํ์ธํ๋ค. */
switch(getchar()) { /* ๋ฌธ์๋ฅผ ์ฝ๋๋ค. */
case 'q': /* ์ฝ์ ๋ฌธ์๊ฐ q์ด๋ฉด ์ข
๋ฃํ๋ค. */
pthread_kill(ptWebserver, SIGINT);
pthread_cancel(ptWebserver);
is_run = 0;
goto END;
};
}
// printf("%20d\t\t\r", i); /* ํ์ฌ ์นด์ดํธํ ์ซ์๋ฅผ ์ถ๋ ฅํ๋ค. */
delay(100); /* 100๋ฐ๋ฆฌ์ด ๋์ ์ฐ๋ค. */
}
END:
printf("Good Bye!\n");
/* ์ฌ์ฉ์ด ๋๋ ์ฅ์น๋ฅผ ์ ๋ฆฌ */
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG1, 0x00);
close(pressure_fd);
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG1, 0x00);
close(temperature_fd);
pthread_mutex_destroy(&pressure_lock); /* ๋ฎคํ
์ค ์ญ์ */
pthread_mutex_destroy(&temperature_lock);
return 0;
}
/* ํค๋ณด๋ ์
๋ ฅ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํจ์ */
int kbhit(void)
{
struct termios oldt, newt; /* ํฐ๋ฏธ๋์ ๋ํ ๊ตฌ์กฐ์ฒด */
int ch, oldf;
tcgetattr(0, &oldt); /* ํ์ฌ ํฐ๋ฏธ๋์ ์ค์ ๋ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค. */
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO); /* ์ ๊ท ๋ชจ๋ ์
๋ ฅ๊ณผ ์์ฝ๋ฅผ ํด์ ํ๋ค. */
tcsetattr(0, TCSANOW, &newt); /* ์ ๊ฐ์ผ๋ก ํฐ๋ฏธ๋์ ์ค์ ํ๋ค. */
oldf = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, oldf | O_NONBLOCK); /* ์
๋ ฅ์ ๋
ผ๋ธ๋กํน ๋ชจ๋๋ก ์ค์ ํ๋ค. */
ch = getchar();
tcsetattr(0, TCSANOW, &oldt); /* ๊ธฐ์กด์ ๊ฐ์ผ๋ก ํฐ๋ฏธ๋์ ์์ฑ์ ๋ฐ๋ก ์ ์ฉํ๋ค. */
fcntl(0, F_SETFL, oldf);
if(ch != EOF) {
ungetc(ch, stdin); /* ์์์ ์ฝ์ ์์น๋ก ์ด์ ์ผ๋ก ํฌ์ธํฐ๋ฅผ ๋๋ ค์ค๋ค. */
return 1;
}
return 0;
}
/* ๊ธฐ์๊ณผ ์จ๋ ๊ณ์ฐ์ ์ํ ํจ์ */
void getPressure(int fd, double *temperature, double *pressure)
{
int result;
unsigned char temp_out_l = 0, temp_out_h = 0; /* ์จ๋๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํ ๋ณ์ */
unsigned char press_out_xl = 0; /* ๊ธฐ์์ ๊ณ์ฐํ๊ธฐ ์ํ ๋ณ์ */
unsigned char press_out_l = 0;
unsigned char press_out_h = 0;
short temp_out = 0; /* ์จ๋์ ์๋ ฅ์ ์ ์ฅํ๊ธฐ ์ํ ๋ณ์ */
int press_out = 0;
/* ์ธก์ ์ด ์๋ฃ๋ ๋๊น์ง ๋๊ธฐ */
do {
delay(25); /* 25๋ฐ๋ฆฌ์ด ๋๊ธฐ */
result = wiringPiI2CReadReg8(fd, CTRL_REG2);
} while(result != 0);
/* ์ธก์ ๋ ์จ๋ ๊ฐ ์ฝ๊ธฐ(2๋ฐ์ดํธ ์ฝ๊ธฐ) */
temp_out_l = wiringPiI2CReadReg8(fd, PTEMP_OUT_L);
temp_out_h = wiringPiI2CReadReg8(fd, PTEMP_OUT_H);
/* ์ธก์ ๋ ๊ธฐ์ ๊ฐ ์ฝ๊ธฐ(3๋ฐ์ดํธ ์ฝ๊ธฐ) */
press_out_xl = wiringPiI2CReadReg8(fd, PRESS_OUT_XL);
press_out_l = wiringPiI2CReadReg8(fd, PRESS_OUT_L);
press_out_h = wiringPiI2CReadReg8(fd, PRESS_OUT_H);
/* ๊ฐ๊ฐ ์ธก์ ํ ๊ฐ๋ค์ ํฉ์ฑํด์ ์จ๋(16๋นํธ)์ ๊ธฐ์(24๋นํธ) ๊ฐ ์์ฑ(๋นํธ/์ํํธ ์ด์ฉ) */
temp_out = temp_out_h << 8 | temp_out_l;
press_out = press_out_h << 16 | press_out_l << 8 | press_out_xl;
/* ์ถ๋ ฅ๊ฐ ๊ณ์ฐ */
*temperature = 42.5 + (temp_out / 480.0);
*pressure = press_out / 4096.0;
}
/* ์จ๋์ ์ต๋๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํ ํจ์ */
void getTemperature(int fd, double *temperature, double *humidity)
{
int result;
/* ์ธก์ ์ด ์๋ฃ๋ ๋๊น์ง ๋๊ธฐ */
do {
delay(25); /* 25๋ฐ๋ฆฌ์ด ๋๊ธฐ */
result = wiringPiI2CReadReg8(fd, CTRL_REG2);
} while(result != 0);
/* ์จ๋(LSB(ADC))๋ฅผ ์ํ ๋ณด์ ๊ฐ(x-๋ฐ์ดํฐ๋ฅผ ์ํ 2์ง์ ) ์ฝ๊ธฐ */
unsigned char t0_out_l = wiringPiI2CReadReg8(fd, T0_OUT_L);
unsigned char t0_out_h = wiringPiI2CReadReg8(fd, T0_OUT_H);
unsigned char t1_out_l = wiringPiI2CReadReg8(fd, T1_OUT_L);
unsigned char t1_out_h = wiringPiI2CReadReg8(fd, T1_OUT_H);
/* ์จ๋(ยฐC)๋ฅผ ์ํ ๋ณด์ ๊ฐ(y-๋ฐ์ดํฐ๋ฅผ ์ํ 2์ง์ ) ์ฝ๊ธฐ */
unsigned char t0_degC_x8 = wiringPiI2CReadReg8(fd, T0_degC_x8);
unsigned char t1_degC_x8 = wiringPiI2CReadReg8(fd, T1_degC_x8);
unsigned char t1_t0_msb = wiringPiI2CReadReg8(fd, T1_T0_MSB);
/* ์ต๋(LSB(ADC))๋ฅผ ์ํ ๋ณด์ ๊ฐ(x-๋ฐ์ดํฐ๋ฅผ ์ํ 2์ง์ ) ์ฝ๊ธฐ */
unsigned char h0_out_l = wiringPiI2CReadReg8(fd, H0_T0_OUT_L);
unsigned char h0_out_h = wiringPiI2CReadReg8(fd, H0_T0_OUT_H);
unsigned char h1_out_l = wiringPiI2CReadReg8(fd, H1_T0_OUT_L);
unsigned char h1_out_h = wiringPiI2CReadReg8(fd, H1_T0_OUT_H);
/*์ต๋(% rH)๋ฅผ ์ํ ๋ณด์ ๊ฐ(y-๋ฐ์ดํฐ๋ฅผ ์ํ 2์ง์ ) ์ฝ๊ธฐ */
unsigned char h0_rh_x2 = wiringPiI2CReadReg8(fd, H0_rH_x2);
unsigned char h1_rh_x2 = wiringPiI2CReadReg8(fd, H1_rH_x2);
/* ๊ฐ๊ฐ ์ธก์ ํ ๊ฐ๋ค์ ํฉ์ฑํด์ ์จ๋(x-๊ฐ) ๊ฐ ์์ฑ(๋นํธ/์ํํธ ์ด์ฉ) */
short s_t0_out = t0_out_h << 8 | t0_out_l;
short s_t1_out = t1_out_h << 8 | t1_out_l;
/* ๊ฐ๊ฐ ์ธก์ ํ ๊ฐ๋ค์ ํฉ์ฑํด์ ์ต๋(x-๊ฐ) ๊ฐ ์์ฑ(๋นํธ/์ํํธ ์ด์ฉ) */
short s_h0_t0_out = h0_out_h << 8 | h0_out_l;
short s_h1_t0_out = h1_out_h << 8 | h1_out_l;
/* 16๋นํธ์ 10๋นํธ์ ๊ฐ ์์ฑ(๋นํธ ๋ง์คํฌ/์ํํธ ์ด์ฉ) */
unsigned short s_t0_degC_x8 = (t1_t0_msb & 3) << 8 | t0_degC_x8;
unsigned short s_t1_degC_x8 = ((t1_t0_msb & 12) >> 2) << 8 | t1_degC_x8;
/* ์จ๋ ๋ณด์ ๊ฐ(y-๊ฐ) ๊ณ์ฐ */
double d_t0_degC = s_t0_degC_x8 / 8.0;
double d_t1_degC = s_t1_degC_x8 / 8.0;
/* ์ต๋ ๋ณด์ ๊ฐ(y-๊ฐ) ๊ณ์ฐ */
double h0_rH = h0_rh_x2 / 2.0;
double h1_rH = h1_rh_x2 / 2.0;
/* ์จ๋์ ์ต๋์ ๊ณ์ฐ์ ์ํ ๋ณด์ ์ ํ ์ง์ ๊ทธ๋ํ 'y = mx + c' ๊ณต์์ ๊ณ์ฐ */
double t_gradient_m = (d_t1_degC - d_t0_degC) / (s_t1_out - s_t0_out);
double t_intercept_c = d_t1_degC - (t_gradient_m * s_t1_out);
double h_gradient_m = (h1_rH - h0_rH) / (s_h1_t0_out - s_h0_t0_out);
double h_intercept_c = h1_rH - (h_gradient_m * s_h1_t0_out);
/* ์ฃผ๋ณ์ ์จ๋ ์ฝ๊ธฐ(2๋ฐ์ดํธ ์ฝ๊ธฐ) */
unsigned char t_out_l = wiringPiI2CReadReg8(fd, TEMP_OUT_L);
unsigned char t_out_h = wiringPiI2CReadReg8(fd, TEMP_OUT_H);
/* 16๋นํธ ๊ฐ ์์ฑ */
short s_t_out = t_out_h << 8 | t_out_l;
/* ์ฃผ๋ณ์ ์ต๋ ์ฝ๊ธฐ(2๋ฐ์ดํธ ์ฝ๊ธฐ) */
unsigned char h_t_out_l = wiringPiI2CReadReg8(fd, H_T_OUT_L);
unsigned char h_t_out_h = wiringPiI2CReadReg8(fd, H_T_OUT_H);
/* 16๋นํธ ๊ฐ ์์ฑ */
short s_h_t_out = h_t_out_h << 8 | h_t_out_l;
/* ์ฃผ๋ณ์ ์จ๋ ๊ณ์ฐ */
*temperature = (t_gradient_m * s_t_out) + t_intercept_c;
/* ์ฃผ๋ณ์ ์ต๋ ๊ณ์ฐ */
*humidity = (h_gradient_m * s_h_t_out) + h_intercept_c;
}
void* webserverFunction(void* arg)
{
int ssock;
pthread_t thread;
struct sockaddr_in servaddr, cliaddr;
unsigned int len;
int port = (int)(arg);
/* ์๋ฒ๋ฅผ ์ํ ์์ผ์ ์์ฑํ๋ค. */
ssock = socket(AF_INET, SOCK_STREAM, 0);
if(ssock == -1) {
perror("socket()");
exit(1);
}
/* ์
๋ ฅ๋ฐ๋ ํฌํธ ๋ฒํธ๋ฅผ ์ด์ฉํด์ ์๋น์ค๋ฅผ ์ด์์ฒด์ ์ ๋ฑ๋กํ๋ค. */
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if(bind(ssock, (struct sockaddr *)&servaddr, sizeof(servaddr))==-1) {
perror("bind()");
exit(1);
}
/* ์ต๋ 10๋์ ํด๋ผ์ด์ธํธ์ ๋์ ์ ์์ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ๋ฅผ ์์ฑํ๋ค. */
if(listen(ssock, 10) == -1) {
perror("listen()");
exit(1);
}
while(is_run) {
char mesg[BUFSIZ];
int csock;
/* ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๊ธฐ๋ค๋ฆฐ๋ค. */
len = sizeof(cliaddr);
csock = accept(ssock, (struct sockaddr*)&cliaddr, &len);
/* ๋คํธ์ํฌ ์ฃผ์๋ฅผ ๋ฌธ์์ด๋ก ๋ณ๊ฒฝ */
inet_ntop(AF_INET, &cliaddr.sin_addr, mesg, BUFSIZ);
printf("Client IP : %s:%d\n", mesg, ntohs(cliaddr.sin_port));
/* ํด๋ผ์ด์ธํธ์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด ์ค๋ ๋๋ฅผ ์์ฑํ๊ณ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ์ฒ๋ฆฌํ๋ค. */
pthread_create(&thread, NULL, clnt_connection, &csock);
// pthread_join(thread, NULL);
}
return 0;
}
void *clnt_connection(void *arg)
{
/* ์ค๋ ๋๋ฅผ ํตํด์ ๋์ด์จ arg๋ฅผ int ํ์ ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ก ๋ณํํ๋ค. */
int csock = *((int*)arg);
FILE *clnt_read, *clnt_write;
char reg_line[BUFSIZ], reg_buf[BUFSIZ];
char method[BUFSIZ], type[BUFSIZ];
char filename[BUFSIZ], *ret;
/* ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ฅผ FILE ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๋ค. */
clnt_read = fdopen(csock, "r");
clnt_write = fdopen(dup(csock), "w");
/* ํ ์ค์ ๋ฌธ์์ด์ ์ฝ์ด์ reg_line ๋ณ์์ ์ ์ฅํ๋ค. */
fgets(reg_line, BUFSIZ, clnt_read);
/* reg_line ๋ณ์์ ๋ฌธ์์ด์ ํ๋ฉด์ ์ถ๋ ฅํ๋ค. */
fputs(reg_line, stdout);
/* ' ' ๋ฌธ์๋ก reg_line์ ๊ตฌ๋ถํด์ ์์ฒญ ๋ผ์ธ์ ๋ด์ฉ(๋ฉ์๋)๋ฅผ ๋ถ๋ฆฌํ๋ค. */
ret = strtok(reg_line, "/ ");
strcpy(method, (ret != NULL)?ret:"");
if(strcmp(method, "POST") == 0) { /* POST ๋ฉ์๋์ผ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๋ค. */
sendOk(clnt_write); /* ๋จ์ํ OK ๋ฉ์์ง๋ฅผ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ธ๋ค. */
goto END;
} else if(strcmp(method, "GET") != 0) { /* GET ๋ฉ์๋๊ฐ ์๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๋ค. */
sendError(clnt_write); /* ์๋ฌ ๋ฉ์์ง๋ฅผ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ธ๋ค. */
goto END;
}
ret = strtok(NULL, " "); /* ์์ฒญ ๋ผ์ธ์์ ๊ฒฝ๋ก(path)๋ฅผ ๊ฐ์ ธ์จ๋ค. */
strcpy(filename, (ret != NULL)?ret:"");
if(filename[0] == '/') { /* ๊ฒฝ๋ก๊ฐ '/'๋ก ์์๋ ๊ฒฝ์ฐ /๋ฅผ ์ ๊ฑฐํ๋ค. */
for(int i = 0, j = 0; i < BUFSIZ; i++, j++) {
if(filename[0] == '/') j++;
filename[i] = filename[j];
if(filename[j] == '\0') break;
}
}
/* URL์ ๊ฒฝ๋ก(path)์ด ์์ ๋ ๊ธฐ๋ณธ ์ฒ๋ฆฌ */
if(!strlen(filename)) strcpy(filename, "index.html");
/* ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด๋ฅผ ์ ์ดํ๊ธฐ ์ํ HTML ์ฝ๋๋ฅผ ๋ถ์ํด์ ์ฒ๋ฆฌํ๋ค. */
if(strstr(filename, "?") != NULL) {
char optLine[BUFSIZ];
char optStr[32][BUFSIZ];
char opt[BUFSIZ], var[BUFSIZ], *tok;
int count = 0;
ret = strtok(filename, "?");
if(ret == NULL) goto END;
strcpy(filename, ret);
ret = strtok(NULL, "?");
if(ret == NULL) goto END;
strcpy(optLine, ret);
/* ์ต์
์ ๋ถ์ํ๋ค. */
tok = strtok(optLine, "&");
while(tok != NULL) {
strcpy(optStr[count++], tok);
tok = strtok(NULL, "&");
}
/* ๋ถ์ํ ์ต์
์ ์ฒ๋ฆฌํ๋ค. */
for(int i = 0; i < count; i++) {
strcpy(opt, strtok(optStr[i], "="));
strcpy(var, strtok(NULL, "="));
printf("%s = %s\n", opt, var);
if(!strcmp(opt, "led") && !strcmp(var, "On")) { /* 8ร8 LED ๋งคํธ๋ฆญ์ค๋ฅผ ์ผฌ */
} else if(!strcmp(opt, "led") && !strcmp(var, "Off")) { /* 8ร8 LED ๋งคํธ๋ฆญ์ค๋ฅผ ๋ */
}
}
}
/* ๋ฉ์์ง ํค๋๋ฅผ ์ฝ์ด์ ํ๋ฉด์ ์ถ๋ ฅํ๊ณ ๋๋จธ์ง๋ ๋ฌด์ํ๋ค. */
do {
fgets(reg_line, BUFSIZ, clnt_read);
fputs(reg_line, stdout);
strcpy(reg_buf, reg_line);
char* buf = strchr(reg_buf, ':');
} while(strncmp(reg_line, "\r\n", 2)); /* ์์ฒญ ํค๋๋ โ\r\nโ์ผ๋ก ๋๋๋ค. */
/* ํ์ผ์ ์ด๋ฆ์ ์ด์ฉํด์ ํด๋ผ์ด์ธํธ๋ก ํ์ผ์ ๋ด์ฉ์ ๋ณด๋ธ๋ค. */
sendData(clnt_write, type, filename);
END:
fclose(clnt_read); /* ํ์ผ์ ์คํธ๋ฆผ์ ๋ซ๋๋ค. */
fclose(clnt_write);
pthread_exit(0); /* ์ค๋ ๋๋ฅผ ์ข
๋ฃ์ํจ๋ค. */
return (void*)NULL;
}
int sendData(FILE* fp, char *ct, char *filename)
{
/* ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ผ ์ฑ๊ณต์ ๋ํ ์๋ต ๋ฉ์์ง */
char protocol[ ] = "HTTP/1.1 200 OK\r\n";
char server[ ] = "Server:Netscape-Enterprise/6.0\r\n";
char cnt_type[ ] = "Content-Type:text/html\r\n";
char end[ ] = "\r\n"; /* ์๋ต ํค๋์ ๋์ ํญ์ \r\n */
char html[BUFSIZ];
double temperature, humidity;
double t_c = 0.0; /* ์จ๋์ ์๋ ฅ์ ์ถ๋ ฅํ๊ธฐ ์ํ ๋ณ์ */
double pressure = 0.0;
/* LPS25H ์ฅ์น ์ด๊ธฐํ */
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG1, 0x00);
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG1, 0x84);
wiringPiI2CWriteReg8(pressure_fd, CTRL_REG2, 0x01);
getPressure(pressure_fd, &t_c, &pressure); /* ๊ธฐ์/์จ๋๋ฅผ ์ํ ํจ์ */
/* HTS221 ์ฅ์น ์ด๊ธฐํ */
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG1, 0x00);
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG1, 0x84);
wiringPiI2CWriteReg8(temperature_fd, CTRL_REG2, 0x01);
getTemperature(temperature_fd, &temperature, &humidity); /* ์จ๋/์ต๋๋ฅผ ์ํ ํจ์ */
sprintf(html, "<html><head><meta http-equiv=\"Content-Type\" " \
"content=\"text/html; charset=UTF-8\" />" \
"<title>Raspberry Pi Controller</title></head><body><table>" \
"<tr><td>Temperature</td><td colspan=2>" \
"<input readonly name=\"temperature\"value=%.3f></td></tr>" \
"<tr><td>Humidity</td><td colspan=2>" \
"<input readonly name=\"humidity\"value=%.3f></td></tr>" \
"<tr><td>Pressure</td><td colspan=2>" \
"<input readonly name=\"pressure\"value=%.3f></td></tr></table>" \
"<form action=\"index.html\" method=\"GET\" "\
"onSubmit=\"document.reload()\"><table>" \
"<tr><td>8x8 LED Matrix</td><td>" \
"<input type=radio name=\"led\" value=\"On\" checked=checked>On</td>" \
"<td><input type=radio name=\"led\" value=\"Off\">Off</td>" \
"</tr><tr><td>Submit</td>" \
"<td colspan=2><input type=submit value=\"Submit\"></td></tr>" \
"</table></form></body></html>",
temperature, humidity, pressure);
fputs(protocol, fp);
fputs(server, fp);
fputs(cnt_type, fp);
fputs(end, fp);
fputs(html, fp);
fflush(fp);
return 0;
}
void sendOk(FILE* fp)
{
/* ํด๋ผ์ด์ธํธ์ ๋ณด๋ผ ์ฑ๊ณต์ ๋ํ HTTP ์๋ต ๋ฉ์์ง */
char protocol[ ] = "HTTP/1.1 200 OK\r\n";
char server[ ] = "Server: Netscape-Enterprise/6.0\r\n\r\n";
fputs(protocol, fp);
fputs(server, fp);
fflush(fp);
}
void sendError(FILE* fp)
{
/* ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ผ ์คํจ์ ๋ํ HTTP ์๋ต ๋ฉ์์ง */
char protocol[ ] = "HTTP/1.1 400 Bad Request\r\n";
char server[ ] = "Server: Netscape-Enterprise/6.0\r\n";
char cnt_len[ ] = "Content-Length:1024\r\n";
char cnt_type[ ] = "Content-Type:text/html\r\n\r\n";
/* ํ๋ฉด์ ํ์๋ HTML์ ๋ด์ฉ */
char content1[ ] = "<html><head><title>BAD Connection</title></head>";
char content2[ ] = "<body><font size=+5>Bad Request</font></body></html>";
printf("send_error\n");
fputs(protocol, fp);
fputs(server, fp);
fputs(cnt_len, fp);
fputs(cnt_type, fp);
fputs(content1, fp);
fputs(content2, fp);
fflush(fp);
}
/*
HTML ๋ฌธ์ ์์ ์จ๋์ ์ต๋ ๋ฑ์ ์ง์ ํ์ํ ์ ์๋๋ก ์ฝ์
ํจ + lED ์ผ๊ณ ๋ ์ ์๋ ๋ผ๋์ค ๋ฒํผ + ์์
์ ์ฐ์ฃผํ๊ณ ๋ชจํฐ๋ฅผ ์ ์ด
์น ๋ธ๋ผ์ฐ์ ์์ ์น ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ๋ <FORM> ํ๊ทธ๋ฅผ ์ฌ์ฉํ๋ค
<FORM> ํ๊ทธ๋ POST ๋ฉ์์ง๋ก ์์ฒญ์ ๋ณด๋ด์ง๋ง, ์ ์น ์๋ฒ๋ GET ๋ฉ์๋๋ง ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์
<FORM> ํ๊ทธ์ method ์์ฑ์ ์ด์ฉํ์ฌ GET ๋ฉ์๋๋ก ๋ณด๋ด๋๋ก ์ค์ ํ๋ค
์น ๋ธ๋ผ์ฐ์ ์์ ์น ํ์ด์ง๋ฅผ ๋ถ๋ฌ๋ค์ฌ์ ์ต์
์ ์ ํํ๊ณ Submit ๋ฒํผ์ ์ ํํ๋ฉด, ์น ์๋ฒ๋ก
'http://์๋ฒ์ฃผ์:ํฌํธ๋ฒํธ/index.html?led=Off' ์์ฒญ์ GET ๋ฉ์๋๋ก ์ ๋ฌ๋๋ค
์น ์๋ฒ์์๋ GET ๋ฉ์๋๋ก ์ ์ก๋ ๋ฉ์์ง๋ฅผ ๋ถ์ํ๊ณ ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด์ GPIO ์ ํด๋น ๋ช
๋ น์ ๋ด๋ฆด ์ ์๋ค
์ฝ๋๋ฅผ ๋น๋ ์ Pthread ๋ผ์ด๋ธ๋ฌ๋ฆฌ, wiringPi ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋ ๋งํฌํด์ผ ํ๋ค
์ฐ๋๋ ์จ์ต๋ ์ธก์ ์ผ์๊ฐ ์์ด์ ์๋ํ์ง ์๋๋ค ใ
gani@gani:~/raspi/NetworkProgramming $ gcc -o rpi6 rpi6.c -lpthread -lwiringPi
gani@gani:~/raspi/NetworkProgramming $ sudo ./rpi6 8080
*/
gcc -o rpi6 rpi6.c -lpthread -lwiringPi
sudo ./rpi6 8080