From 21ed0435b925d7bc5f92c56eaba5a44b6ee8434e Mon Sep 17 00:00:00 2001 From: shaun feakes Date: Fri, 16 Mar 2018 12:18:15 -0500 Subject: [PATCH] Update to messaging and checksum --- aq_programmer.c | 4 +- aq_serial.c | 11 +- aqualink.h | 4 +- aqualinkd.c | 28 +-- release/aqualinkd | Bin 217380 -> 221544 bytes release/serial_logger | Bin 24156 -> 24156 bytes serial_logger.c | 2 +- utils.1.c | 440 ------------------------------------------ utils.c | 23 +++ utils.h | 1 + 10 files changed, 54 insertions(+), 459 deletions(-) delete mode 100644 utils.1.c diff --git a/aq_programmer.c b/aq_programmer.c index d1bb26b..049ddc5 100644 --- a/aq_programmer.c +++ b/aq_programmer.c @@ -889,8 +889,8 @@ bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageR //logMessage(LOG_ERR, "Could not select MENU of Aqualink control panel\n"); logMessage(LOG_DEBUG, "Programming mode: did not find '%s'\n",message); return false; - } - logMessage(LOG_DEBUG, "Programming mode: found message '%s' in '%s'\n",message,aq_data->last_message); + } else if (message != NULL) + logMessage(LOG_DEBUG, "Programming mode: found message '%s' in '%s'\n",message,aq_data->last_message); return true; } diff --git a/aq_serial.c b/aq_serial.c index 5ca7bda..39f28d5 100644 --- a/aq_serial.c +++ b/aq_serial.c @@ -238,9 +238,6 @@ void send_ack(int fd, unsigned char command) } - - - // Reads the bytes of the next incoming packet, and // returns when a good packet is available in packet // fd: the file descriptor to read the bytes from @@ -335,6 +332,14 @@ int get_packet(int fd, unsigned char* packet) } } + if (generate_checksum(packet, index) != packet[index-3]){ + logMessage(LOG_WARNING, "Serial read bad checksum, ignoring\n"); + return 0; + } else if (index < AQ_MINPKTLEN) { + logMessage(LOG_WARNING, "Serial read too small, (but good checksum), need to understand this better\n"); + return 0; + } + logMessage(LOG_DEBUG_SERIAL, "Serial read %d bytes\n",index); // Return the packet length. return index; diff --git a/aqualink.h b/aqualink.h index bddf7c7..a2dacb3 100644 --- a/aqualink.h +++ b/aqualink.h @@ -66,8 +66,8 @@ struct aqualinkdata char date[AQ_MSGLEN]; char time[AQ_MSGLEN]; //char datestr[DATE_STRING_LEN]; - char message[AQ_MSGLONGLEN]; // NSF just temp for PDA crap - char *last_message; // Be careful using this, can get core dumps. + char last_message[AQ_MSGLONGLEN+1]; // NSF just temp for PDA crap + //char *last_message; // Be careful using this, can get core dumps. //char *display_message; unsigned char raw_status[AQ_PSTLEN]; aqled aqualinkleds[TOTAL_LEDS]; diff --git a/aqualinkd.c b/aqualinkd.c index 23a1ffa..f874eaf 100644 --- a/aqualinkd.c +++ b/aqualinkd.c @@ -269,8 +269,9 @@ void processMessage(char *message) static bool _initWithRS = false; static bool _gotREV = false; // NSF replace message with msg - msg = cleanwhitespace(message); - _aqualink_data.last_message = msg; + msg = stripwhitespace(message); + strcpy(_aqualink_data.last_message, msg); + //_aqualink_data.last_message = _aqualink_data.message; //_aqualink_data.display_message = NULL; //aqualink_strcpy(_aqualink_data.message, msg); @@ -361,7 +362,7 @@ void processMessage(char *message) aq_programmer(AQ_SEND_CMD, (char *)KEY_ENTER, &_aqualink_data); } else { - logMessage(LOG_DEBUG, "Ignoring '%s'\n",msg); + logMessage(LOG_DEBUG_SERIAL, "Ignoring '%s'\n",msg); //_aqualink_data.display_message = msg; } @@ -371,15 +372,16 @@ void processMessage(char *message) void processPDAMessage(char *message) { + static bool nextMessageTemp = false; char *msg; - msg = cleanwhitespace(message); - _aqualink_data.last_message = msg; + msg = stripwhitespace(message); + strcpy(_aqualink_data.last_message, msg); logMessage(LOG_INFO, "RS PDA Message :- '%s'\n",msg); - if (_aqualink_data.message != NULL && strncasecmp(_aqualink_data.message, "AIR", 3) == 0) - { + if (nextMessageTemp == true) { + nextMessageTemp = false; _aqualink_data.temp_units = FAHRENHEIT; // RS PDA Message :- '73` 66`' _aqualink_data.air_temp = atoi(msg); @@ -388,12 +390,16 @@ void processPDAMessage(char *message) //aq_programmer(AQ_SEND_CMD, (char *)KEY_ENTER, &_aqualink_data); aq_programmer(AQ_PDA_INIT, NULL, &_aqualink_data); - } else if(strstr(msg, "REV ") != NULL) { // 'REV MMM' - aq_programmer(AQ_PDA_INIT, NULL, &_aqualink_data); + } + else if (strncasecmp(_aqualink_data.last_message, "AIR", 3) == 0) { + nextMessageTemp = true; + } + else if(strstr(msg, "REV ") != NULL) { // 'REV MMM' + //aq_programmer(AQ_PDA_INIT, NULL, &_aqualink_data); } //_aqualink_data.last_message = msg; - strncpy(_aqualink_data.message, msg,AQ_MSGLONGLEN); + strncpy(_aqualink_data.last_message, msg,AQ_MSGLONGLEN); // We processed the next message, kick any threads waiting on the message. kick_aq_program_thread(&_aqualink_data); @@ -410,7 +416,7 @@ bool process_packet(unsigned char* packet, int length) // Check packet against last check if different. if (memcmp(packet, last_packet, length) == 0) { - logMessage(LOG_DEBUG, "RS Received duplicate, ignoring.\n",length); + logMessage(LOG_DEBUG_SERIAL, "RS Received duplicate, ignoring.\n",length); return rtn; } else { memcpy(last_packet, packet, length); diff --git a/release/aqualinkd b/release/aqualinkd index 72da8e853d86eb099012bf9c7934f2cbbe920ef8..aa3028c24a640d4071a75fb9d94c50d1cb1f6a63 100755 GIT binary patch delta 49094 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 delta 48410 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 diff --git a/serial_logger.c b/serial_logger.c index 36c1f11..b714371 100644 --- a/serial_logger.c +++ b/serial_logger.c @@ -10,7 +10,7 @@ #include "aq_serial.h" #include "utils.h" -#define SLOG_MAX 40 +#define SLOG_MAX 80 #define PACKET_MAX 1000 typedef struct serial_id_log { diff --git a/utils.1.c b/utils.1.c deleted file mode 100644 index cf8d85a..0000000 --- a/utils.1.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (c) 2017 Shaun Feakes - All rights reserved - * - * You may use redistribute and/or modify this code under the terms of - * the GNU General Public License version 2 as published by the - * Free Software Foundation. For the terms of this license, - * see . - * - * You are free to use this software under the terms of the GNU General - * Public License, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * https://github.com/sfeakes/aqualinkd - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _UTILS_C_ -#define _UTILS_C_ -#endif - -#include "utils.h" - -//#define MAXCFGLINE 265 -#define TIMESTAMP_LENGTH 30 - - -static bool _daemonise = false; -static bool _log2file = false; -static int _log_level = -1; -static char *_log_filename = NULL; -//static char _log_filename[256]; - -void setLoggingPrms(int level , bool deamonized, char* log_file) -{ - _log_level = level; - _daemonise = deamonized; - - if (log_file == NULL || strlen(log_file) <= 0) { - _log2file = false; - } else { - _log2file = true; - _log_filename = log_file; - //strcpy(_log_filename, log_file); - } -} - -int getLogLevel() -{ - return _log_level; -} - - -/* -* This function reports the error and -* exits back to the shell: -*/ -void displayLastSystemError (const char *on_what) -{ - fputs (strerror (errno), stderr); - fputs (": ", stderr); - fputs (on_what, stderr); - fputc ('\n', stderr); - - if (_daemonise == TRUE) - { - logMessage (LOG_ERR, "%d : %s", errno, on_what); - closelog (); - } -} - -/* -From -- syslog.h -- -#define LOG_EMERG 0 // system is unusable -#define LOG_ALERT 1 // action must be taken immediately -#define LOG_CRIT 2 // critical conditions -#define LOG_ERR 3 // error conditions -#define LOG_WARNING 4 // warning conditions -#define LOG_NOTICE 5 // normal but significant condition -#define LOG_INFO 6 // informational -#define LOG_DEBUG 7 // debug-level messages -*/ - -char *elevel2text(int level) -{ - switch(level) { - case LOG_ERR: - return "Error:"; - break; - case LOG_WARNING: - return "Warning:"; - break; - case LOG_NOTICE: - return "Notice:"; - break; - case LOG_INFO: - return "Info:"; - break; - case LOG_DEBUG: - default: - return "Debug:"; - break; - } - - return ""; -} - -int text2elevel(char* level) -{ - if (strcmp(level, "DEBUG_SERIAL") == 0) { - return LOG_DEBUG_SERIAL; - } - if (strcmp(level, "DEBUG") == 0) { - return LOG_DEBUG; - } - else if (strcmp(level, "INFO") == 0) { - return LOG_INFO; - } - else if (strcmp(level, "WARNING") == 0) { - return LOG_WARNING; - } - else if (strcmp(level, "NOTICE") == 0) { - return LOG_NOTICE; - } - else if (strcmp(level, "INFO") == 0) { - return LOG_INFO; - } - - return LOG_ERR; -} - -void timestamp(char* time_string) -{ - time_t now; - struct tm *tmptr; - - time(&now); - tmptr = localtime(&now); - strftime(time_string, TIMESTAMP_LENGTH, "%b-%d-%y %H:%M:%S %p ", tmptr); -} - -void trimwhitespace(char *str) -{ - char *end; - end = str + strlen(str) - 1; - while(end > str && isspace(*end)) end--; - - *(end+1) = 0; -} - -char *cleanwhitespace(char *str) -{ - char *end; - - // Trim leading space - while(isspace(*str)) str++; - - if(*str == 0) // All spaces? - return str; - - // Trim trailing space - end = str + strlen(str) - 1; - while(end > str && isspace(*end)) end--; - - // Write new null terminator - *(end+1) = 0; - - return str; -} - - -/* -char *cleanquotes(char *str) -{ - char *end; - // Trim leading whitespace - //while(isspace(*str)) str++; - //if(*str == 0) // All spaces? - // return str; -syslog(LOG_INFO, "String to clean %s\n", str); - - while(*str=='"' || *str== '\'' || *str==' ') str++; - if(*str == 0) // All spaces - return str; - - end = str + strlen(str) - 1; - while(end > str && (*end=='"' || *end== '\'' || *end==' ')) end--; - - // Write new null terminator - *(end+1) = 0; - -syslog(LOG_INFO, "String cleaned %s\n", str); - - return str; -} -*/ -int cleanint(char*str) -{ - if (str == NULL) - return 0; - - str = cleanwhitespace(str); - return atoi(str); -} - -void test(int msg_level, char *msg) -{ - char buffer[256]; - - sprintf(buffer,"Level %d | MsgLvl %d | Dmn %d | LF %d | %s - %s",_log_level,msg_level,_daemonise,_log2file,_log_filename,msg); - if ( buffer[strlen(buffer)-1] != '\n') { - strcat(buffer, "\n"); - } - - int fp = open("/var/log/aqualink.log", O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if (fp != -1) { - write(fp, buffer, strlen(buffer) ); - close(fp); - } else { - syslog(LOG_ERR, "Can't open file /var/log/aqualink.log"); - } -} - -void logMessage(int msg_level, char *format, ...) -{ - char buffer[512]; - va_list args; - va_start(args, format); - strncpy(buffer, " ", 8); - vsprintf (&buffer[8], format, args); - va_end(args); - - //test(msg_level, buffer); - //fprintf (stderr, buffer); - - if (_log_level == -1) { - fprintf (stderr, buffer); - syslog (msg_level, "%s", &buffer[8]); - closelog (); - } else if (msg_level > _log_level) { - return; - } - - if (_daemonise == TRUE) - { - syslog (msg_level, "%s", &buffer[8]); - closelog (); - //return; - } - - if (_log2file == TRUE && _log_filename != NULL) { - int len; - char *strLevel = elevel2text(msg_level); - - strncpy(buffer, strLevel, strlen(strLevel)); - - len = strlen(buffer); - - //printf( " '%s' last chrs '%d''%d'\n", buffer, buffer[len-1],buffer[len]); - - if ( buffer[len-1] != '\n') { - strcat(buffer, "\n"); - } - - char time[TIMESTAMP_LENGTH]; - int fp = open(_log_filename, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if (fp != -1) { - timestamp(time); - write(fp, time, strlen(time) ); - write(fp, buffer, strlen(buffer) ); - close(fp); - } else { - if (_daemonise == TRUE) - syslog(LOG_ERR, "Can't open log file\n %s", buffer); - else - fprintf (stderr, "Can't open debug log\n %s", buffer); - } - } - - if (_daemonise == FALSE) { - if (msg_level == LOG_ERR) { - fprintf(stderr, "%s", buffer); - } else { - printf("%s", buffer); - } - } -} - -void daemonise (char *pidFile, void (*main_function) (void)) -{ - FILE *fp = NULL; - pid_t process_id = 0; - pid_t sid = 0; - - _daemonise = true; - - /* Check we are root */ - if (getuid() != 0) - { - logMessage(LOG_ERR,"Can only be run as root\n"); - exit(EXIT_FAILURE); - } - - int pid_file = open (pidFile, O_CREAT | O_RDWR, 0666); - int rc = flock (pid_file, LOCK_EX | LOCK_NB); - if (rc) - { - if (EWOULDBLOCK == errno) - ; // another instance is running - //fputs ("\nAnother instance is already running\n", stderr); - logMessage(LOG_ERR,"\nAnother instance is already running\n"); - exit (EXIT_FAILURE); - } - - process_id = fork (); - // Indication of fork() failure - if (process_id < 0) - { - displayLastSystemError ("fork failed!"); - // Return failure in exit status - exit (EXIT_FAILURE); - } - // PARENT PROCESS. Need to kill it. - if (process_id > 0) - { - fp = fopen (pidFile, "w"); - - if (fp == NULL) - logMessage(LOG_ERR,"can't write to PID file %s",pidFile); - else - fprintf(fp, "%d", process_id); - - fclose (fp); - logMessage (LOG_DEBUG, "process_id of child process %d \n", process_id); - // return success in exit status - exit (EXIT_SUCCESS); - } - //unmask the file mode - umask (0); - //set new session - sid = setsid (); - if (sid < 0) - { - // Return failure - displayLastSystemError("Failed to fork process"); - exit (EXIT_FAILURE); - } - // Change the current working directory to root. - chdir ("/"); - // Close stdin. stdout and stderr - close (STDIN_FILENO); - close (STDOUT_FILENO); - close (STDERR_FILENO); - - // this is the first instance - (*main_function) (); - - return; -} - -int count_characters(const char *str, char character) -{ - const char *p = str; - int count = 0; - - do { - if (*p == character) - count++; - } while (*(p++)); - - return count; -} - -bool text2bool(char *str) -{ - str = cleanwhitespace(str); - if (strcasecmp (str, "YES") == 0 || strcasecmp (str, "ON") == 0) - return TRUE; - else - return FALSE; -} - -char *bool2text(bool val) -{ - if(val == TRUE) - return "YES"; - else - return "NO"; -} - -// (50°F - 32) x .5556 = 10°C -float degFtoC(float degF) -{ - return ((degF-32) / 1.8); -} -// 30°C x 1.8 + 32 = 86°F -float degCtoF(float degC) -{ - return (degC * 1.8 + 32); -} - -#include - -void delay (unsigned int howLong) // Microseconds (1000000 = 1 second) -{ - struct timespec sleeper, dummy ; - - sleeper.tv_sec = (time_t)(howLong / 1000) ; - sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; - - nanosleep (&sleeper, &dummy) ; -} - -char* stristr(const char* haystack, const char* needle) { - do { - const char* h = haystack; - const char* n = needle; - while (tolower((unsigned char) *h) == tolower((unsigned char ) *n) && *n) { - h++; - n++; - } - if (*n == 0) { - return (char *) haystack; - } - } while (*haystack++); - return 0; -} \ No newline at end of file diff --git a/utils.c b/utils.c index cf8d85a..b1060e7 100644 --- a/utils.c +++ b/utils.c @@ -161,6 +161,7 @@ void trimwhitespace(char *str) *(end+1) = 0; } +//Move existing pointer char *cleanwhitespace(char *str) { char *end; @@ -181,6 +182,28 @@ char *cleanwhitespace(char *str) return str; } +// Return new pointer +char *stripwhitespace(char *str) +{ + char *end; + char *start = str; + + // Trim leading space + while(isspace(*start)) start++; + + if(*start == 0) // All spaces? + return start; + + // Trim trailing space + end = str + strlen(str) - 1; + while(end > str && isspace(*end)) end--; + + // Write new null terminator + *(end+1) = 0; + + return start; +} + /* char *cleanquotes(char *str) diff --git a/utils.h b/utils.h index 05a99bc..46afb9f 100644 --- a/utils.h +++ b/utils.h @@ -40,6 +40,7 @@ char *elevel2text(int level); char *cleanwhitespace(char *str); //char *cleanquotes(char *str); void trimwhitespace(char *str); +char *stripwhitespace(char *str); int cleanint(char*str); bool text2bool(char *str); char *bool2text(bool val);