|
@@ -0,0 +1,249 @@
|
|
|
|
|
+#include <sys/socket.h>
|
|
|
|
|
+#include <netinet/in.h>
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+#include <strings.h>
|
|
|
|
|
+#include <stdlib.h>
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
+#include <errno.h>
|
|
|
|
|
+#include <arpa/inet.h>
|
|
|
|
|
+#include <inttypes.h>
|
|
|
|
|
+#include <signal.h>
|
|
|
|
|
+
|
|
|
|
|
+volatile int sockfd = 0;
|
|
|
|
|
+
|
|
|
|
|
+typedef void (*CommandHandler)(char*);
|
|
|
|
|
+
|
|
|
|
|
+// Определяем тип функции преобразования
|
|
|
|
|
+typedef void (*ConvertFunc)(char *str, void *output);
|
|
|
|
|
+
|
|
|
|
|
+void handleCloseSignal(int signal);
|
|
|
|
|
+void handleFreqCmd(char* recvBuff);
|
|
|
|
|
+void handleLdCmd(char* recvBuff);
|
|
|
|
|
+void handlePowCmd(char* recvBuff);
|
|
|
|
|
+void handleArmCmd(char* recvBuff);
|
|
|
|
|
+void handleAttCmd(char* recvBuff);
|
|
|
|
|
+void handleIdnCmd(char* recvBuff);
|
|
|
|
|
+void processCommand(char* recvBuff);
|
|
|
|
|
+void convertToUInt16(char *str, void *output);
|
|
|
|
|
+void convertToUint64(char *str, void *output);
|
|
|
|
|
+void convertToDouble(char *str, void *output);
|
|
|
|
|
+void splitLexeme(uint8_t *ptrSCPI, void *numOutAndValue, size_t elementSize, ConvertFunc convertFunc);
|
|
|
|
|
+
|
|
|
|
|
+//Обработчик ошибок
|
|
|
|
|
+void error(const char *msg)
|
|
|
|
|
+{
|
|
|
|
|
+ perror(msg);
|
|
|
|
|
+
|
|
|
|
|
+ if (sockfd != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ close(sockfd);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ exit(1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//Обработчик сигнала SIGINT завершения программы при нажатии Ctrl+C
|
|
|
|
|
+void handleCloseSignal(int signal)
|
|
|
|
|
+{
|
|
|
|
|
+ if (signal == SIGINT)
|
|
|
|
|
+ {
|
|
|
|
|
+ printf("\nCaught signal %d, closing socket and exiting...\n", signal);
|
|
|
|
|
+ if (sockfd != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ close(sockfd);
|
|
|
|
|
+ }
|
|
|
|
|
+ exit(0);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//handleXXXXCmd - обработчики команд
|
|
|
|
|
+void handleFreqCmd(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ printf("\nTMSG44:FREQ\n");
|
|
|
|
|
+ uint64_t freq[1] = {0};
|
|
|
|
|
+
|
|
|
|
|
+ splitLexeme(recvBuff, freq, sizeof(freq[0]), convertToUint64);
|
|
|
|
|
+
|
|
|
|
|
+ printf("%" PRId64 "\n", freq[0]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void handleLdCmd(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ printf("\nTMSG44:LD?\n");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void handlePowCmd(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ printf("\nTMSG44:POW\n");
|
|
|
|
|
+ double pow[1] = {0};
|
|
|
|
|
+
|
|
|
|
|
+ splitLexeme(recvBuff, pow, sizeof(pow[0]), convertToDouble);
|
|
|
|
|
+ printf("%f\n", pow[0]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void handleArmCmd(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ printf("\nTMSG44:ARM\n");
|
|
|
|
|
+ uint16_t armCode[1] = {0};
|
|
|
|
|
+
|
|
|
|
|
+ splitLexeme(recvBuff, armCode, sizeof(armCode[0]), convertToUInt16);
|
|
|
|
|
+ printf("\n%u\n", armCode[0]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void handleAttCmd(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ printf("\nTMSG44:ATT\n");
|
|
|
|
|
+ uint16_t attCode[1] = {0};
|
|
|
|
|
+
|
|
|
|
|
+ splitLexeme(recvBuff, attCode, sizeof(attCode[0]), convertToUInt16);
|
|
|
|
|
+ printf("\n%u\n", attCode[0]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void handleIdnCmd(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ printf("\n*IDN?\n");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+typedef struct {
|
|
|
|
|
+ const char* command;
|
|
|
|
|
+ CommandHandler handler;
|
|
|
|
|
+} Command;
|
|
|
|
|
+
|
|
|
|
|
+//Массив структур Command, который связывает строки команд с соответствующими функциями.
|
|
|
|
|
+Command commands[] = {
|
|
|
|
|
+ {"TMSG44:FREQ ", handleFreqCmd},
|
|
|
|
|
+ {"TMSG44:LD?", handleLdCmd},
|
|
|
|
|
+ {"TMSG44:POW ", handlePowCmd},
|
|
|
|
|
+ {"TMSG44:ARM ", handleArmCmd},
|
|
|
|
|
+ {"TMSG44:ATT ", handleAttCmd},
|
|
|
|
|
+ {"*IDN?", handleIdnCmd},
|
|
|
|
|
+ {NULL, NULL} // Завершающий элемент для обозначения конца массива
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+//Проходим по массиву команд и ищем команду, которая совпадает с началом строки recvBuff.
|
|
|
|
|
+//Если команда найдена, вызывается соответствующая функция-обработчик
|
|
|
|
|
+void processCommand(char* recvBuff)
|
|
|
|
|
+{
|
|
|
|
|
+ for (int i = 0; commands[i].command != NULL; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!strncasecmp(recvBuff, commands[i].command, strlen(commands[i].command)))
|
|
|
|
|
+ {
|
|
|
|
|
+ commands[i].handler(recvBuff);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ printf("\nUnknown command: %s\n", recvBuff);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//=========================================================//
|
|
|
|
|
+
|
|
|
|
|
+// Преобразование строки в uint16_t
|
|
|
|
|
+void convertToUInt16(char *str, void *output)
|
|
|
|
|
+{
|
|
|
|
|
+ *(uint16_t *)output = (uint16_t)strtoul(str, NULL, 10);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Преобразование строки в unsigned long long int
|
|
|
|
|
+void convertToUint64(char *str, void *output)
|
|
|
|
|
+{
|
|
|
|
|
+ *(uint64_t *)output = (uint64_t)strtoull(str, NULL, 10);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Преобразование строки в double
|
|
|
|
|
+void convertToDouble(char *str, void *output)
|
|
|
|
|
+{
|
|
|
|
|
+ *(double *)output = strtod(str, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Универсальная функция для разделения строки на лексемы
|
|
|
|
|
+void splitLexeme(uint8_t *ptrSCPI, void *numOutAndValue, size_t elementSize, ConvertFunc convertFunc)
|
|
|
|
|
+{
|
|
|
|
|
+ uint8_t counter = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // Разделители лексем
|
|
|
|
|
+ char charSeparator[3] = {' ', '\n', '\\'};
|
|
|
|
|
+ char *ptrLexeme = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ // Инициализируем функцию
|
|
|
|
|
+ ptrLexeme = strtok((char *)ptrSCPI, charSeparator);
|
|
|
|
|
+
|
|
|
|
|
+ // Ищем лексемы разделенные разделителем
|
|
|
|
|
+ ptrLexeme = strtok(NULL, charSeparator);
|
|
|
|
|
+
|
|
|
|
|
+ // Ищем лексемы строки
|
|
|
|
|
+ while (ptrLexeme) {
|
|
|
|
|
+ // Проверяем, является ли первый символ лексемы числом
|
|
|
|
|
+ if(('0' <= ptrLexeme[0]) && (ptrLexeme[0] <= '9')) {
|
|
|
|
|
+ // Преобразуем строку с числом в число
|
|
|
|
|
+ convertFunc(ptrLexeme, (uint8_t *)numOutAndValue + counter * elementSize);
|
|
|
|
|
+ counter++;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Ищем лексемы разделенные разделителем
|
|
|
|
|
+ ptrLexeme = strtok(NULL, charSeparator);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+//====================================================//
|
|
|
|
|
+
|
|
|
|
|
+int main(int argc, char *argv[])
|
|
|
|
|
+{
|
|
|
|
|
+ //argv[1] = "127.0.0.1";
|
|
|
|
|
+ int n = 0;
|
|
|
|
|
+ char recvBuff[1024];
|
|
|
|
|
+ struct sockaddr_in serv_addr;
|
|
|
|
|
+
|
|
|
|
|
+ // Установка обработчика сигналов
|
|
|
|
|
+ signal(SIGINT, handleCloseSignal);
|
|
|
|
|
+
|
|
|
|
|
+ if(argc != 2)
|
|
|
|
|
+ {
|
|
|
|
|
+ printf("\n Usage: %s <ip of server> \n",argv[0]);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ memset(recvBuff, '0',sizeof(recvBuff));
|
|
|
|
|
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ error("Error : Could not create socket");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ memset(&serv_addr, '0', sizeof(serv_addr));
|
|
|
|
|
+
|
|
|
|
|
+ serv_addr.sin_family = AF_INET;
|
|
|
|
|
+ serv_addr.sin_port = htons(5000);
|
|
|
|
|
+
|
|
|
|
|
+ if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ error("inet_pton error occured");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ error("Error : Connect Failed");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ recvBuff[n] = 0;
|
|
|
|
|
+ if(fputs(recvBuff, stdout) == EOF)
|
|
|
|
|
+ {
|
|
|
|
|
+ printf("\n Error : Fputs error\n");
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ //Запуск парсера команд
|
|
|
|
|
+ processCommand(recvBuff);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (n == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Соединение закрыто сервером
|
|
|
|
|
+ printf("\n Server closed the connection\n");
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (n < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ error("Read error");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ close(sockfd);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|