перепись кода кирилла под пк от нервосетки, скомпилися, запустился, но ещё не проверен

This commit is contained in:
Aleksey Khristolyubov 2025-09-15 08:37:17 +07:00
parent 2bdf5fd4fd
commit 10bcb00929
6 changed files with 417 additions and 0 deletions

16
clang_client/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Run sim808_app",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/sim808_app",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"preLaunchTask": "build"
}
]
}

3
clang_client/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"idf.pythonInstallPath": "/usr/bin/python3"
}

21
clang_client/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "gcc",
"args": [
"-std=c99",
"-O2",
"-g",
"main.c",
"Drivers/sim808.c",
"-o",
"sim808_app"
],
"group": "build",
"problemMatcher": ["$gcc"]
}
]
}

View File

@ -0,0 +1,321 @@
#define _POSIX_C_SOURCE 200809L
#include "sim808.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/time.h>
/* -------------------- Внутреннее состояние (аналог глобалей из прошивки) -------------------- */
static int g_sock = -1;
static char* g_packet_buf = NULL;
static size_t g_packet_len = 0;
static size_t g_packet_cap = 0;
static const size_t PACKET_INIT_CAP = 4096; /* стартовая ёмкость буфера */
static const size_t PACKET_MAX_CAP = (size_t)32 * 1024 * 1024; /* ограничение от дурака: 32 МБ */
/* -------------------- Утилиты -------------------- */
static sim800_stat_t ensure_capacity(size_t need_extra)
{
if (g_packet_len + need_extra <= g_packet_cap)
return SIM808_OK;
size_t new_cap = g_packet_cap ? g_packet_cap : PACKET_INIT_CAP;
while (new_cap < g_packet_len + need_extra) {
if (new_cap > PACKET_MAX_CAP / 2) { /* защита от переполнения и чрезмерного роста */
new_cap = PACKET_MAX_CAP;
break;
}
new_cap *= 2;
}
if (new_cap < g_packet_len + need_extra)
return SIM808_ERR;
char* p = (char*)realloc(g_packet_buf, new_cap);
if (!p) return SIM808_ERR;
g_packet_buf = p;
g_packet_cap = new_cap;
return SIM808_OK;
}
static void packet_reset_buffer(void)
{
free(g_packet_buf);
g_packet_buf = NULL;
g_packet_len = 0;
g_packet_cap = 0;
}
/* Получить строковый IP из sockaddr (локальный/удалённый) */
static sim800_stat_t sockaddr_to_ipstr(const struct sockaddr* sa, char* out, size_t outsz)
{
if (!sa || !out || outsz == 0) return SIM808_ERR;
void* addr_ptr = NULL;
if (sa->sa_family == AF_INET) {
addr_ptr = &((struct sockaddr_in*)sa)->sin_addr;
} else if (sa->sa_family == AF_INET6) {
addr_ptr = &((struct sockaddr_in6*)sa)->sin6_addr;
} else {
return SIM808_ERR;
}
const char* r = inet_ntop(sa->sa_family, addr_ptr, out, (socklen_t)outsz);
return (r ? SIM808_OK : SIM808_ERR);
}
/* -------------------- Реализация API -------------------- */
sim800_stat_t sim808_init(void)
{
/* На ПК ничего инициализировать не нужно */
return SIM808_OK;
}
sim800_stat_t sim808_open_connection(char* apn, char* host, char* port, char* self_ip)
{
(void)apn; /* на ПК APN не используется */
/* Если сокет уже открыт — закроем */
if (g_sock >= 0) {
close(g_sock);
g_sock = -1;
}
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC; /* IPv4 или IPv6 */
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo* res = NULL;
int gai = getaddrinfo(host, port, &hints, &res);
if (gai != 0 || !res) {
return SIM808_ERR;
}
int sockfd = -1;
struct addrinfo* it = res;
for (; it; it = it->ai_next) {
sockfd = (int)socket(it->ai_family, it->ai_socktype, it->ai_protocol);
if (sockfd < 0) continue;
/* Можно поставить таймауты (опционально) */
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
if (connect(sockfd, it->ai_addr, (socklen_t)it->ai_addrlen) == 0) {
g_sock = sockfd;
break;
}
close(sockfd);
sockfd = -1;
}
freeaddrinfo(res);
if (g_sock < 0) return SIM808_ERR;
/* По запросу — вернуть локальный IP интерфейса, через который установилось соединение */
if (self_ip) {
struct sockaddr_storage sa_local;
socklen_t slen = (socklen_t)sizeof(sa_local);
if (getsockname(g_sock, (struct sockaddr*)&sa_local, &slen) == 0) {
if (sockaddr_to_ipstr((struct sockaddr*)&sa_local, self_ip, 64) != SIM808_OK) {
/* если не смогли — просто оставим как есть */
self_ip[0] = '\0';
}
} else {
self_ip[0] = '\0';
}
}
return SIM808_OK;
}
sim800_stat_t sim808_close_connection(void)
{
if (g_sock >= 0) {
close(g_sock);
g_sock = -1;
}
return SIM808_OK;
}
sim800_stat_t packet_start(void)
{
packet_reset_buffer();
/* выделим стартовую ёмкость сразу, чтобы меньше реаллокаций */
g_packet_buf = (char*)malloc(PACKET_INIT_CAP);
if (!g_packet_buf) {
g_packet_cap = 0;
return SIM808_ERR;
}
g_packet_cap = PACKET_INIT_CAP;
g_packet_len = 0;
return SIM808_OK;
}
sim800_stat_t packet_data(char* msg)
{
if (!msg) return SIM808_ERR;
if (g_sock < 0) return SIM808_ERR; /* нет соединения */
if (!g_packet_buf && packet_start() != SIM808_OK) /* безопасности ради */
return SIM808_ERR;
size_t n = strlen(msg); /* как и в вашей версии — работаем со строками */
if (n == 0) return SIM808_OK;
if (ensure_capacity(n) != SIM808_OK)
return SIM808_ERR;
memcpy(g_packet_buf + g_packet_len, msg, n);
g_packet_len += n;
return SIM808_OK;
}
sim800_stat_t packet_end(void)
{
if (g_sock < 0) {
packet_reset_buffer();
return SIM808_ERR;
}
size_t total = g_packet_len;
size_t sent = 0;
while (sent < total) {
ssize_t r = send(g_sock, g_packet_buf + sent, total - sent, 0);
if (r < 0) {
if (errno == EINTR) continue;
packet_reset_buffer();
return SIM808_ERR;
}
if (r == 0) { /* неожиданное закрытие */
packet_reset_buffer();
return SIM808_ERR;
}
sent += (size_t)r;
}
packet_reset_buffer();
return SIM808_OK;
}
sim800_stat_t sim808_send_msg(char* msg)
{
sim800_stat_t ret = SIM808_OK;
ret = packet_start();
if (ret != SIM808_OK) return ret;
ret = packet_data(msg);
if (ret != SIM808_OK) { packet_reset_buffer(); return ret; }
ret = packet_end();
return ret;
}
/* -------------------- Заглушки “модемных” функций -------------------- */
sim800_stat_t reset(void) { return SIM808_OK; }
sim800_stat_t echo_off(void) { return SIM808_OK; }
sim800_stat_t check_sim_connection(void) { return SIM808_OK; }
sim800_stat_t chech_sim_card(void) { return SIM808_OK; }
sim800_stat_t check_network_registration(void) { return SIM808_OK; }
sim800_stat_t check_gprs_registration(void) { return SIM808_OK; }
sim800_stat_t close_ip_sessions(void) { return SIM808_OK; }
sim800_stat_t set_single_ip_mode(void) { return SIM808_OK; }
sim800_stat_t set_apn(char* apn, char* user, char* pass) { (void)apn; (void)user; (void)pass; return SIM808_OK; }
sim800_stat_t start_gprs(void) { return SIM808_OK; }
/* Возвращаем локальный IP уже открытого сокета */
sim800_stat_t get_ip(char* ip_ret)
{
if (!ip_ret) return SIM808_ERR;
if (g_sock < 0) { ip_ret[0] = '\0'; return SIM808_ERR; }
struct sockaddr_storage sa_local;
socklen_t slen = (socklen_t)sizeof(sa_local);
if (getsockname(g_sock, (struct sockaddr*)&sa_local, &slen) != 0) {
ip_ret[0] = '\0';
return SIM808_ERR;
}
return sockaddr_to_ipstr((struct sockaddr*)&sa_local, ip_ret, 64);
}
/* Непосредственные TCP-обёртки (оставлены для совместимости) */
sim800_stat_t open_tcp(char* host, char* port)
{
return sim808_open_connection(NULL, host, port, NULL);
}
sim800_stat_t close_tcp(void)
{
return sim808_close_connection();
}
/* -------------------- Заглушки обработчиков/таймеров -------------------- */
void sim808_gprs_usart_handler(void) { /* на ПК не используется */ }
void sim808_timeout_processing(void) { /* на ПК не используется */ }
/* -------------------- Демонстрационный стейт-машин (как в вашем исходнике) -------------------- */
static unsigned char self_ip_buf[64] = {0};
static unsigned char cmd = 0;
enum {
CMD_NONE = 0,
CMD_SIM808_OPEN_CONNECTION,
CMD_SIM808_SEND_SMG,
CMD_SIM808_CLOSE_CONNECTION,
};
static sim800_stat_t conn_open = SIM808_ERR;
static sim800_stat_t conn_clos = SIM808_ERR;
static sim800_stat_t msg_sent = SIM808_ERR;
void sim808_demo_send(void)
{
switch (cmd)
{
case CMD_SIM808_OPEN_CONNECTION:
cmd = CMD_NONE;
conn_open = SIM808_ERR;
conn_open = sim808_open_connection(
"unused-apn", /* игнорируется */
(char*)"212.193.61.100", /* или домен */
(char*)"5000",
(char*)self_ip_buf /* вернём локальный IP интерфейса */
);
break;
case CMD_SIM808_SEND_SMG:
cmd = CMD_NONE;
msg_sent = SIM808_ERR;
msg_sent = sim808_send_msg("biba");
break;
case CMD_SIM808_CLOSE_CONNECTION:
cmd = CMD_NONE;
conn_clos = SIM808_ERR;
conn_clos = sim808_close_connection();
break;
default:
break;
}
}

View File

@ -0,0 +1,41 @@
#ifndef SRC_DRIVERS_SIM808_H_
#define SRC_DRIVERS_SIM808_H_
#include <stddef.h>
typedef enum
{
SIM808_OK = 0,
SIM808_ERR = -1
} sim800_stat_t;
sim800_stat_t sim808_init(void);
sim800_stat_t sim808_open_connection(char* apn, char* host, char* port, char* self_ip);
sim800_stat_t sim808_close_connection(void);
/* Пакетная отправка: start → (data)* → end */
sim800_stat_t packet_start(void);
sim800_stat_t packet_data(char* msg); /* добавляет строку (strlen), бинарные нули не поддерживаются */
sim800_stat_t packet_end(void); /* отправляет накопленное */
sim800_stat_t reset(void); /* заглушка */
sim800_stat_t echo_off(void); /* заглушка */
sim800_stat_t check_sim_connection(void); /* заглушка */
sim800_stat_t chech_sim_card(void); /* заглушка */
sim800_stat_t check_network_registration(void); /* заглушка */
sim800_stat_t check_gprs_registration(void); /* заглушка */
sim800_stat_t close_ip_sessions(void); /* заглушка */
sim800_stat_t set_single_ip_mode(void); /* заглушка */
sim800_stat_t set_apn(char* apn, char* username, char* password); /* заглушка */
sim800_stat_t start_gprs(void); /* заглушка */
sim800_stat_t get_ip(char* ip_ret); /* вернёт локальный IP подключенного сокета (если есть) */
sim800_stat_t open_tcp(char* host, char* port);
sim800_stat_t close_tcp(void);
void sim808_gprs_usart_handler(void); /* заглушка */
void sim808_timeout_processing(void); /* заглушка */
void sim808_demo_send(void); /* демонстрационная машина состояний — как в исходнике */
sim800_stat_t sim808_send_msg(char* msg); /* удобная обёртка */
#endif /* SRC_DRIVERS_SIM808_H_ */

15
clang_client/main.c Normal file
View File

@ -0,0 +1,15 @@
#include "Drivers/sim808.h"
sim800_stat_t sim808_init_ok = SIM808_ERR;
int main(void)
{
sim808_init_ok = sim808_init();
while (1)
{
sim808_demo_send();
}
return 0;
}