# Yocto에서 센서 데이터 처리

Yocto 프로젝트에서 센서 데이터를 처리하는 과정은 시스템 설계, 데이터 수집, 데이터 처리 및 데이터 전송의 총 4단계로 구분할 수 있다. 이 장에서는 이러한 각 단계를 심도 있게 다룰 것이다.

#### 시스템 설계

센서 데이터를 처리하기 위한 Yocto 프로젝트의 시스템 설계는 다음과 같은 단계로 이루어진다.

* **하드웨어 선택**: 사용하려는 센서와 그 센서를 지원하는 하드웨어 플랫폼 (예: Raspberry Pi, BeagleBone 등) 선택.
* **소프트웨어 스택 구성**: 필요한 드라이버 및 라이브러리를 포함한 Yocto 이미지 생성.

#### 센서 드라이버 설치 및 설정

센서 드라이버는 센서와 상호작용하는 소프트웨어 모듈이다. Yocto 프로젝트의 레시피 파일을 수정하여 센서 드라이버를 포함시킬 수 있다.

**레시피 파일**

Yocto에서 레시피 파일은 *\*.bb* 확장자를 가지며, 특정 패키지를 빌드하기 위한 지침을 담고 있다.

```bitbake
DESCRIPTION = "Example recipe for sensor driver"
LICENSE = "GPLv2"
SRC_URI = "file://sensor_driver.c"

do_compile() {
    oe_runmake
}

do_install() {
    install -d ${D}
    install -m 0755 ${WORKDIR}/sensor_driver${D}/usr/bin/
}
```

#### 데이터 수집

센서 데이터 수집은 크게 로우 레벨 데이터 접근과 고레벨 데이터 접근으로 나눌 수 있다. 로우 레벨 접근 방식에서는 센서가 제공하는 원시 데이터를 그대로 읽어 오며, 고레벨 접근 방식에서는 데이터를 해석하여 의미 있는 정보를 추출한다.

**로우 레벨 데이터 접근**

로우레벨 데이터 접근은 센서의 하드웨어 레지스터를 직접 읽고 쓰는 과정이다.

```c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define SENSOR_IOCTL_MAGIC 's'
#define SENSOR_IOCTL_READ _IOR(SENSOR_IOCTL_MAGIC, 1, int)

int main() {
    int fd = open("/dev/sensor0", O_RDONLY);
    if (fd < 0) {
        perror("Failed to open device");
        return -1;
    }

    int data;
    if (ioctl(fd, SENSOR_IOCTL_READ, &data) < 0) {
        perror("Failed to read data");
        close(fd);
        return -1;
    }

    printf("Sensor data: %d\n", data);
    close(fd);
    return 0;
}
```

#### 데이터 처리

수집한 데이터를 처리하는 단계에서는 필터링, 변환, 분석 등의 작업을 수행한다.

**데이터 필터링**

필터링은 잡음을 제거하고 원하는 신호만을 추출하는 과정이다. 예를 들어, 저역 필터를 사용하여 고주파 잡음을 제거할 수 있다.

```python
import numpy as np

def low_pass_filter(data, cutoff_frequency, sampling_rate):
    nyquist_rate = sampling_rate / 2.0
    normal_cutoff = cutoff_frequency / nyquist_rate
    b, a = butter(1, normal_cutoff, btype='low', analog=False)
    return lfilter(b, a, data)
```

**데이터 변환**

변환 단계는 수집된 센서 데이터를 다른 형태로 변경하는 과정이다. 예를 들어, 아날로그 신호를 디지털 신호로 변환하거나, 원시 데이터를 물리적 단위로 변환한다.

```python
def raw_to_temperature(raw_value):
    # Assuming 10mV per degree Celsius and 500mV offset
    return (raw_value - 500) / 10.0
```

#### 데이터 전송

처리된 데이터를 저장하거나, 다른 시스템으로 전송할 수 있다. 데이터 전송 방법에는 로컬 저장소에 저장, 클라우드로 전송, 혹은 다른 디바이스로 실시간 스트리밍하는 방식 등이 있다.

**로컬 저장소에 저장**

데이터를 파일 시스템이나 데이터베이스에 저장할 수 있다. 간단한 예로, 텍스트 파일에 데이터를 저장할 수 있다.

```python
data = {
    "timestamp": "2023-10-01T10:00:00Z",
    "temperature": 23.5,
    "humidity": 55.0
}

with open("/path/to/data.txt", "a") as file:
    file.write(f"{data['timestamp']},{data['temperature']},{data['humidity']}\n")
```

**클라우드 전송**

처리된 데이터를 클라우드 서버로 전송하여 중앙에서 관리할 수 있다. 이를 위해 HTTP 요청을 사용한 예를 들 수 있다.

```python
import requests

data = {
    "timestamp": "2023-10-01T10:00:00Z",
    "temperature": 23.5,
    "humidity": 55.0
}

response = requests.post("http://example.com/api/sensor_data", json=data)
if response.status_code == 200:
    print("Data sent successfully")
else:
    print(f"Failed to send data: {response.status_code}")
```

**실시간 스트리밍**

실시간 데이터를 다른 장치로 스트리밍하는 방법으로는 MQTT 프로토콜이 자주 사용된다.

```python
import paho.mqtt.client as mqtt

client = mqtt.Client()
client.connect("mqtt.example.com", 1883, 60)

data = {
    "timestamp": "2023-10-01T10:00:00Z",
    "temperature": 23.5,
    "humidity": 55.0
}

client.publish("sensor/data", str(data))
client.disconnect()
```

#### 예제 프로젝트

여기서는 예제 프로젝트를 통해 위의 과정을 종합한 실습을 진행해보겠다. 우리의 목표는 간단한 온도 센서를 통해 수집한 데이터를 처리하고 클라우드 서버로 전송하는 것이다.

**1단계: 하드웨어 및 드라이버 설정**

* **하드웨어 플랫폼**: Raspberry Pi
* **센서**: DS18B20 온도 센서

레시피 파일을 사용하여 드라이버를 설치한다.

```bitbake
DESCRIPTION = "DS18B20 temperature sensor driver"
LICENSE = "GPLv2"
SRC_URI = "file://ds18b20.c"

do_compile() {
    oe_runmake
}

do_install() {
    install -d ${D}
    install -m 0755 ${WORKDIR}/ds18b20${D}/usr/bin/
}
```

**2단계: 데이터 수집**

보드에서 DS18B20 센서의 데이터를 읽어온다.

```c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define SENSOR_IOCTL_MAGIC 's'
#define SENSOR_IOCTL_READ _IOR(SENSOR_IOCTL_MAGIC, 1, int)

int main() {
    int fd = open("/dev/ds18b20", O_RDONLY);
    if (fd < 0) {
        perror("Failed to open device");
        return -1;
    }

    int data;
    if (ioctl(fd, SENSOR_IOCTL_READ, &data) < 0) {
        perror("Failed to read data");
        close(fd);
        return -1;
    }

    printf("Temperature data: %d\n", data);
    close(fd);
    return 0;
}
```

**3단계: 데이터 처리**

온도 데이터를 필터링하고 변환한다.

```python
import numpy as np

def raw_to_temperature(raw_value):
    return (raw_value / 16.0) * 0.0625

raw_value = 300
temperature = raw_to_temperature(raw_value)
print(f"Temperature: {temperature}°C")
```

**4단계: 데이터 전송**

온도 데이터를 클라우드 서버로 전송한다.

```python
import requests

data = {
    "timestamp": "2023-10-01T10:00:00Z",
    "temperature": 23.5
}

response = requests.post("http://example.com/api/sensor_data", json=data)
if response.status_code == 200:
    print("Data sent successfully")
else:
    print(f"Failed to send data: {response.status_code}")
```

이 예제를 통해 Yocto 프로젝트를 활용하여 센서 데이터를 처리하고 전송하는 과정을 이해할 수 있다. 이러한 과정은 IoT 시스템 설계의 기초가 되며, 다양한 응용 분야에 활용될 수 있다.

####
