From cefd8e8c1f8610f42fa97477f56660266d8617da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=B2=9C=20=EC=A7=84=EA=B0=95?= <jjjjjk12@ajou.ac.kr>
Date: Fri, 29 Nov 2024 16:43:37 +0900
Subject: [PATCH] =?UTF-8?q?feat(c):=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=20?=
 =?UTF-8?q?=EB=B0=8F=20C=20=EC=84=9C=EB=B2=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 server-node-control/control.c | 309 ++++++++++++++++++++++++++++++++++
 1 file changed, 309 insertions(+)
 create mode 100644 server-node-control/control.c

diff --git a/server-node-control/control.c b/server-node-control/control.c
new file mode 100644
index 0000000..9691937
--- /dev/null
+++ b/server-node-control/control.c
@@ -0,0 +1,309 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+
+#define BUFFER_SIZE 1024
+#define PORT 12345
+#define MAX_CLIENTS 5
+
+#define PWM 0
+#define VALUE_MAX 256
+#define DIRECTION_MAX 256
+
+typedef struct {
+    int socket;
+    struct sockaddr_in address;
+} ClientData;
+
+int pySocket, cSocket, clientCnt = 0;
+pthread_t pyThread, clientThreads[MAX_CLIENTS];
+ClientData clients[MAX_CLIENTS];
+
+static int PWMExport(int pwmnum) {
+#define BUFFER_MAX 3
+  char buffer[BUFFER_MAX];
+  int fd, byte;
+
+  // TODO: Enter the export path.
+  fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
+  if (-1 == fd) {
+    fprintf(stderr, "Failed to open export for export!\n");
+    return (-1);
+  }
+
+  byte = snprintf(buffer, BUFFER_MAX, "%d", pwmnum);
+  write(fd, buffer, byte);
+  close(fd);
+
+  sleep(1);
+
+  return (0);
+}
+
+static int PWMUnexport(int pwmnum) {
+#define BUFFER_MAX 3
+  char buffer[BUFFER_MAX];
+  int fd, byte;
+
+  // TODO: Enter the export path.
+  fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY);
+  if (-1 == fd) {
+    fprintf(stderr, "Failed to open export for unexport!\n");
+    return (-1);
+  }
+
+  byte = snprintf(buffer, BUFFER_MAX, "%d", pwmnum);
+  write(fd, buffer, byte);
+  close(fd);
+
+  sleep(1);
+
+  return (0);
+}
+
+static int PWMEnable(int pwmnum) {
+  static const char s_enable_str[] = "1";
+
+  char path[DIRECTION_MAX];
+  int fd;
+
+  // TODO: Enter the enable path.
+  snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm0/enable", pwmnum);
+  fd = open(path, O_WRONLY);
+  if (-1 == fd) {
+    fprintf(stderr, "Failed to open in enable!\n");
+    return -1;
+  }
+
+  write(fd, s_enable_str, strlen(s_enable_str));
+  close(fd);
+
+  return (0);
+}
+static int PWMWritePeriod(int pwmnum, int value) {
+  char s_value_str[VALUE_MAX];
+  char path[VALUE_MAX];
+  int fd, byte;
+
+  // TODO: Enter the period path.
+  snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/period", pwmnum);
+  fd = open(path, O_WRONLY);
+  if (-1 == fd) {
+    fprintf(stderr, "Failed to open in period!\n");
+    return (-1);
+  }
+  byte = snprintf(s_value_str, VALUE_MAX, "%d", value);
+
+  if (-1 == write(fd, s_value_str, byte)) {
+    fprintf(stderr, "Failed to write value in period!\n");
+    close(fd);
+    return -1;
+  }
+  close(fd);
+
+  return (0);
+}
+
+static int PWMWriteDutyCycle(int pwmnum, int value) {
+  char s_value_str[VALUE_MAX];
+  char path[VALUE_MAX];
+  int fd, byte;
+
+  // TODO: Enter the duty_cycle path.
+  snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/duty_cycle", pwmnum);
+  fd = open(path, O_WRONLY);
+  if (-1 == fd) {
+    fprintf(stderr, "Failed to open in duty cycle!\n");
+    return (-1);
+  }
+  byte = snprintf(s_value_str, VALUE_MAX, "%d", value);
+
+  if (-1 == write(fd, s_value_str, byte)) {
+    fprintf(stderr, "Failed to write value in duty cycle!\n");
+    close(fd);
+    return -1;
+  }
+  close(fd);
+
+  return (0);
+}
+
+// 수신 스레드 함수
+void *ClientToServer(void *idx) {
+    int i = *((int*) idx);
+    char buffer[BUFFER_SIZE];
+    char ip[INET_ADDRSTRLEN];
+    int len;
+
+    while ((len = recv(clients[i].socket, buffer, BUFFER_SIZE, 0)) > 0) {
+        buffer[len] = '\0';
+        printf("Received from client %d: %s", &clients[i].address.sin_addr, buffer);
+        inet_ntop(AF_INET, &clients[i].address.sin_addr, ip, INET_ADDRSTRLEN);
+        if (send(pySocket, buffer, strlen(buffer), 0) < 0) {
+            perror("Error sending message to server");
+        }
+    }
+
+    if (len == 0) {
+        printf("Client disconnected: %d\n", clients[i].socket);
+    } else if (len == -1) {
+        perror("recv failed");
+    }
+    clientCnt--;
+    close(clients[i].socket);
+}
+
+// 서버에서 메시지 수신하는 스레드
+void *ServerToClient() {
+    char buffer[BUFFER_SIZE];
+    int len;
+    while (1) {
+        len = read(pySocket, buffer, BUFFER_SIZE - 1);
+        if (len <= 0) {
+            printf("Server disconnected\n");
+            close(pySocket);
+            exit(0);
+        }
+        buffer[len] = '\0';
+        printf("Received from server: %s\n", buffer);
+
+        if (buffer[2] == 'Y') {
+            // 차단기 개방
+            printf("차단기 개방\n");
+            if (PWMExport(PWM)) printf("export error\n");
+            if (PWMWritePeriod(PWM, 20000000)) printf("period error\n");
+            if (PWMWriteDutyCycle(PWM, 0)) printf("duty error\n");
+            if (PWMEnable(PWM)) printf("enable error\n");
+            if (PWMWriteDutyCycle(PWM, 2000000)) printf("duty error2\n");
+            usleep(100000);
+            if (PWMUnexport(PWM)) printf("unexport error\n");
+        }
+
+        else if (buffer[2] == 'P') {
+            // 충전기 노드에 주차 사실 알림
+            if (send(clients[0].socket, buffer, strlen(buffer), 0) < 0) {
+                perror("Error forwarding message to client");
+            }
+        }
+
+        else if (buffer[2] == 'E') {
+            // 충전기 노드에 주차 사실 알림
+            if (send(clients[0].socket, buffer, strlen(buffer), 0) < 0) {
+                perror("Error forwarding message to client");
+            }
+            if (PWMExport(PWM)) printf("export error\n");
+            if (PWMWritePeriod(PWM, 20000000)) printf("period error\n");
+            if (PWMWriteDutyCycle(PWM, 0)) printf("duty error\n");
+            if (PWMEnable(PWM)) printf("enable error\n");
+            if (PWMWriteDutyCycle(PWM, 950000)) printf("duty error2\n");
+            usleep(100000);
+            if (PWMUnexport(PWM)) printf("unexport error\n");
+        }
+
+        else if (buffer[2] == 'F') {
+            // 충전기 노드에 화재 사실 알림
+            // 화재 노드에 화재 사실 알림
+            if (send(clients[0].socket, buffer, strlen(buffer), 0) < 0) {
+                perror("Error forwarding message to client");
+            }
+
+            if (send(clients[3].socket, buffer, strlen(buffer), 0) < 0) {
+                perror("Error forwarding message to client");
+            }
+        }
+    }
+}
+
+int main() {
+    struct sockaddr_in pyAddr, cAddr, clientAddr;
+    pthread_attr_t attr, attr2, at[3];
+    struct sched_param param, param2;
+    socklen_t clientAddrLen = sizeof(clientAddr);
+    param.sched_priority=3;
+    param2.sched_priority=2;
+
+    pthread_attr_init(&attr);
+    pthread_attr_setschedpolicy(&attr, SCHED_RR);
+    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+    pthread_attr_setschedparam(&attr, &param);
+
+    pthread_attr_init(&attr2);
+    pthread_attr_setschedpolicy(&attr2, SCHED_RR);
+    pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED);
+    pthread_attr_setschedparam(&attr2, &param2);
+    at[0] = at[1] = attr2;
+    at[2] = attr;
+
+    // 서버로 연결할 클라이언트 소켓 생성
+    if ((pySocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+        perror("Socket creation error");
+        return -1;
+    }
+
+    // 서버로 메시지 전송할 소켓 설정
+    pyAddr.sin_family = AF_INET;
+    pyAddr.sin_port = htons(49152);
+    if (inet_pton(AF_INET, "127.0.0.1", &pyAddr.sin_addr) <= 0) {
+        perror("Invalid address / Address not supported");
+        return -1;
+    }
+    if (connect(pySocket, (struct sockaddr *)&pyAddr, sizeof(pyAddr)) < 0) {
+        perror("Connection failed");
+        return -1;
+    }
+    printf("서버에 연결되었습니다.\n");
+
+    // 클라이언트를 받을 서버 소켓 설정
+    if ((cSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+        perror("Socket failed");
+        return -1;
+    }
+    cAddr.sin_family = AF_INET;
+    cAddr.sin_addr.s_addr = INADDR_ANY;
+    cAddr.sin_port = htons(PORT);
+
+    if (bind(cSocket, (struct sockaddr *)&cAddr, sizeof(cAddr)) < 0) {
+        perror("Bind failed");
+        close(cSocket);
+        return -1;
+    }
+
+    if (listen(cSocket, 3) < 0) {
+        perror("Listen failed");
+        close(cSocket);
+        return -1;
+    }
+
+    // 서버 수신용 스레드 시작
+    pthread_create(&pyThread, NULL, ServerToClient, NULL);
+
+    while (clientCnt < MAX_CLIENTS) {
+        int x;
+        char ip[INET_ADDRSTRLEN];
+        if ((x = accept(cSocket, (struct sockaddr *)&clientAddr, &clientAddrLen)) < 0) {
+            perror("Accept failed");
+            continue;
+        }
+
+        ClientData *tmp = (ClientData *)malloc(sizeof(ClientData));
+        tmp->socket = x;
+        tmp->address = clientAddr;
+        clients[clientCnt] = *tmp;
+        inet_ntop(AF_INET, &tmp->address.sin_addr, ip, INET_ADDRSTRLEN);
+        int idx = ip[11] - '7';
+
+        if (pthread_create(&clientThreads[idx], &at[idx], ClientToServer, (void *)&idx) < 0) {
+            perror("Failed to create thread");
+            close(x);
+        }
+
+    }
+
+    close(pySocket);
+    close(cSocket);
+    return 0;
+}
-- 
GitLab