mirror of https://github.com/sfeakes/AqualinkD.git
Version 1.3.8
parent
51a8b686a5
commit
62f776fa31
2
Makefile
2
Makefile
|
@ -42,7 +42,7 @@ ifeq ($(DEBUG), true)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c
|
SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c
|
||||||
LR_SRC = log_reader.c aq_serial.c utils.c
|
LR_SRC = log_reader.c aq_serial.c utils.c packetLogger.c
|
||||||
PL_EXSRC = aq_serial.c
|
PL_EXSRC = aq_serial.c
|
||||||
PL_EXOBJ = aq_serial_player.o
|
PL_EXOBJ = aq_serial_player.o
|
||||||
PL_SRC := $(filter-out aq_serial.c, $(SRCS))
|
PL_SRC := $(filter-out aq_serial.c, $(SRCS))
|
||||||
|
|
|
@ -66,6 +66,10 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
|
||||||
* http://aqualink.ip/simple.html <- (Simple opion if you don't like the above)
|
* http://aqualink.ip/simple.html <- (Simple opion if you don't like the above)
|
||||||
* http://aqualink.ip/simulator.html <- (RS8 All Button Control Panel simulator)
|
* http://aqualink.ip/simulator.html <- (RS8 All Button Control Panel simulator)
|
||||||
#<a name="release"></a>
|
#<a name="release"></a>
|
||||||
|
# Update in Release 1.3.8
|
||||||
|
* Fixed PDA mode from 1.3.7
|
||||||
|
* Added SWG Boost to PDA
|
||||||
|
* More updates to protocol code for Jandy and Pentair.
|
||||||
# Update in Release 1.3.7
|
# Update in Release 1.3.7
|
||||||
* PDA SUPPORT IS BROKEN IN 1.3.7 DON'T UPGRADE IF YOU'RE USING PDA Mode
|
* PDA SUPPORT IS BROKEN IN 1.3.7 DON'T UPGRADE IF YOU'RE USING PDA Mode
|
||||||
* PDA Note:- Due to changes to speed up programming the control panel, PDA mode does not function correctly, I will come back and fix this, but I don't have the time for this release.
|
* PDA Note:- Due to changes to speed up programming the control panel, PDA mode does not function correctly, I will come back and fix this, but I don't have the time for this release.
|
||||||
|
|
|
@ -121,7 +121,7 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data)
|
||||||
// Are we in programming mode
|
// Are we in programming mode
|
||||||
if (aq_data->active_thread.thread_id != 0) {
|
if (aq_data->active_thread.thread_id != 0) {
|
||||||
if ( ((_pgm_command == KEY_MENU || aq_data->active_thread.ptype == AQ_SET_TIME) && aq_data->last_packet_type == CMD_STATUS) ||
|
if ( ((_pgm_command == KEY_MENU || aq_data->active_thread.ptype == AQ_SET_TIME) && aq_data->last_packet_type == CMD_STATUS) ||
|
||||||
(aq_data->active_thread.ptype != AQ_SET_TIME && last_sent_was_cmd == false) ||
|
(pda_mode() == false && aq_data->active_thread.ptype != AQ_SET_TIME && last_sent_was_cmd == false) ||
|
||||||
(pda_mode() == true && aq_data->last_packet_type == CMD_STATUS)
|
(pda_mode() == true && aq_data->last_packet_type == CMD_STATUS)
|
||||||
//(pda_mode() == true && last_sent_was_cmd == false)
|
//(pda_mode() == true && last_sent_was_cmd == false)
|
||||||
) {
|
) {
|
||||||
|
@ -132,8 +132,10 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data)
|
||||||
cmd = _pgm_command;
|
cmd = _pgm_command;
|
||||||
_pgm_command = NUL;
|
_pgm_command = NUL;
|
||||||
logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);*/
|
logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);*/
|
||||||
|
} else if (_pgm_command != NUL) {
|
||||||
|
logMessage(LOG_DEBUG, "RS Waiting to send cmd '0x%02hhx' (programming)\n", _pgm_command);
|
||||||
} else {
|
} else {
|
||||||
logMessage(LOG_DEBUG, "RS Waiting to send cmd '0x%02hhx'\n", _pgm_command);
|
logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' empty queue (programming)\n", cmd);
|
||||||
}
|
}
|
||||||
} else if (_stack_place > 0 && aq_data->last_packet_type == CMD_STATUS ) {
|
} else if (_stack_place > 0 && aq_data->last_packet_type == CMD_STATUS ) {
|
||||||
cmd = _commands[0];
|
cmd = _commands[0];
|
||||||
|
@ -286,7 +288,8 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
|
||||||
type != AQ_GET_AUX_LABELS &&
|
type != AQ_GET_AUX_LABELS &&
|
||||||
#endif
|
#endif
|
||||||
type != AQ_GET_POOL_SPA_HEATER_TEMPS &&
|
type != AQ_GET_POOL_SPA_HEATER_TEMPS &&
|
||||||
type != AQ_SET_FRZ_PROTECTION_TEMP) {
|
type != AQ_SET_FRZ_PROTECTION_TEMP &&
|
||||||
|
type != AQ_SET_BOOST) {
|
||||||
logMessage(LOG_ERR, "Selected Programming mode '%d' not supported with PDA mode control panel\n",type);
|
logMessage(LOG_ERR, "Selected Programming mode '%d' not supported with PDA mode control panel\n",type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -646,6 +649,12 @@ STOP BOOST POOL
|
||||||
*/
|
*/
|
||||||
int val = atoi((char*)threadCtrl->thread_args);
|
int val = atoi((char*)threadCtrl->thread_args);
|
||||||
|
|
||||||
|
if (pda_mode() == true) {
|
||||||
|
set_PDA_aqualink_boost(aq_data, val);
|
||||||
|
cleanAndTerminateThread(threadCtrl);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
logMessage(LOG_DEBUG, "programming BOOST to %s\n", val==true?"On":"Off");
|
logMessage(LOG_DEBUG, "programming BOOST to %s\n", val==true?"On":"Off");
|
||||||
|
|
||||||
if ( select_menu_item(aq_data, "BOOST POOL") != true ) {
|
if ( select_menu_item(aq_data, "BOOST POOL") != true ) {
|
||||||
|
@ -1313,8 +1322,15 @@ void waitfor_queue2empty()
|
||||||
delay(50);
|
delay(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pgm_command != NUL)
|
if (_pgm_command != NUL) {
|
||||||
|
if (pda_mode()) {
|
||||||
|
// Wait for longer in PDA mode since it's slower.
|
||||||
|
while ( (_pgm_command != NUL) && ( i++ < 100) ) {
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
logMessage(LOG_WARNING, "Send command Queue did not empty, timeout\n");
|
logMessage(LOG_WARNING, "Send command Queue did not empty, timeout\n");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
687
aq_serial.c
687
aq_serial.c
|
@ -31,8 +31,638 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "packetLogger.h"
|
#include "packetLogger.h"
|
||||||
|
|
||||||
|
//#define USE_AQ_SERIAL_OLD
|
||||||
|
|
||||||
|
#ifndef USE_AQ_SERIAL_OLD // Substansial changes to core component, make sure we can role back easily
|
||||||
|
|
||||||
|
static struct termios _oldtio;
|
||||||
|
|
||||||
|
void send_packet(int fd, unsigned char *packet, int length);
|
||||||
|
//unsigned char getProtocolType(unsigned char* packet);
|
||||||
|
|
||||||
|
bool _pda_mode = false;
|
||||||
|
void set_pda_mode(bool mode)
|
||||||
|
{
|
||||||
|
if (mode)
|
||||||
|
logMessage(LOG_NOTICE, "AqualinkD is using PDA mode\n");
|
||||||
|
|
||||||
|
_pda_mode = mode;
|
||||||
|
}
|
||||||
|
bool pda_mode()
|
||||||
|
{
|
||||||
|
return _pda_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* get_packet_type(unsigned char* packet , int length)
|
||||||
|
{
|
||||||
|
static char buf[15];
|
||||||
|
|
||||||
|
if (length <= 0 )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
switch (packet[PKT_CMD]) {
|
||||||
|
case CMD_ACK:
|
||||||
|
return "Ack";
|
||||||
|
break;
|
||||||
|
case CMD_STATUS:
|
||||||
|
return "Status";
|
||||||
|
break;
|
||||||
|
case CMD_MSG:
|
||||||
|
return "Message";
|
||||||
|
break;
|
||||||
|
case CMD_MSG_LONG:
|
||||||
|
return "Lng Message";
|
||||||
|
break;
|
||||||
|
case CMD_PROBE:
|
||||||
|
return "Probe";
|
||||||
|
break;
|
||||||
|
case CMD_GETID:
|
||||||
|
return "GetID";
|
||||||
|
break;
|
||||||
|
case CMD_PERCENT:
|
||||||
|
return "AR %%";
|
||||||
|
break;
|
||||||
|
case CMD_PPM:
|
||||||
|
return "AR PPM";
|
||||||
|
break;
|
||||||
|
case CMD_PDA_0x05:
|
||||||
|
return "PDA Unknown";
|
||||||
|
break;
|
||||||
|
case CMD_PDA_0x1B:
|
||||||
|
return "PDA Init (*guess*)";
|
||||||
|
break;
|
||||||
|
case CMD_PDA_HIGHLIGHT:
|
||||||
|
return "PDA Hlight";
|
||||||
|
break;
|
||||||
|
case CMD_PDA_CLEAR:
|
||||||
|
return "PDA Clear";
|
||||||
|
break;
|
||||||
|
case CMD_PDA_SHIFTLINES:
|
||||||
|
return "PDA Shiftlines";
|
||||||
|
break;
|
||||||
|
case CMD_PDA_HIGHLIGHTCHARS:
|
||||||
|
return "PDA C_HlightChar";
|
||||||
|
break;
|
||||||
|
case CMD_IAQ_MSG:
|
||||||
|
return "iAq Message";
|
||||||
|
break;
|
||||||
|
case CMD_IAQ_MENU_MSG:
|
||||||
|
return "iAq Menu";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(buf, "Unknown '0x%02hhx'", packet[PKT_CMD]);
|
||||||
|
return buf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate and return checksum of packet.
|
||||||
|
int generate_checksum(unsigned char* packet, int length)
|
||||||
|
{
|
||||||
|
int i, sum, n;
|
||||||
|
|
||||||
|
n = length - 3;
|
||||||
|
sum = 0;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
sum += (int) packet[i];
|
||||||
|
return(sum & 0x0ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_jandy_checksum(unsigned char* packet, int length)
|
||||||
|
{
|
||||||
|
if (generate_checksum(packet, length) == packet[length-3])
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_pentair_checksum(unsigned char* packet, int length)
|
||||||
|
{
|
||||||
|
//printf("check_pentair_checksum \n");
|
||||||
|
int i, sum, n;
|
||||||
|
n = packet[8] + 9;
|
||||||
|
//n = packet[8] + 8;
|
||||||
|
sum = 0;
|
||||||
|
for (i = 3; i < n; i++) {
|
||||||
|
//printf("Sum 0x%02hhx\n",packet[i]);
|
||||||
|
sum += (int) packet[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("Check High 0x%02hhx = 0x%02hhx = 0x%02hhx\n",packet[n], packet[length-2],((sum >> 8) & 0xFF) );
|
||||||
|
//printf("Check Low 0x%02hhx = 0x%02hhx = 0x%02hhx\n",packet[n + 1], packet[length-1], (sum & 0xFF) );
|
||||||
|
|
||||||
|
// Check against caculated length
|
||||||
|
if (sum == (packet[length-2] * 256 + packet[length-1]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check against actual # length
|
||||||
|
if (sum == (packet[n] * 256 + packet[n+1])) {
|
||||||
|
logMessage(LOG_ERR, "Pentair checksum is accurate but length is not\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void generate_pentair_checksum(unsigned char* packet, int length)
|
||||||
|
{
|
||||||
|
int i, sum, n;
|
||||||
|
n = packet[8] + 9;
|
||||||
|
//n = packet[8] + 6;
|
||||||
|
sum = 0;
|
||||||
|
for (i = 3; i < n; i++) {
|
||||||
|
//printf("Sum 0x%02hhx\n",packet[i]);
|
||||||
|
sum += (int) packet[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
packet[n+1] = (unsigned char) (sum & 0xFF); // Low Byte
|
||||||
|
packet[n] = (unsigned char) ((sum >> 8) & 0xFF); // High Byte
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protocolType getProtocolType(unsigned char* packet) {
|
||||||
|
if (packet[0] == DLE)
|
||||||
|
return JANDY;
|
||||||
|
else if (packet[0] == PP1)
|
||||||
|
return PENTAIR;
|
||||||
|
|
||||||
|
return P_UNKNOWN;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
unsigned char getProtocolType(unsigned char* packet) {
|
||||||
|
if (packet[0] == DLE)
|
||||||
|
return PCOL_JANDY;
|
||||||
|
else if (packet[0] == PP1)
|
||||||
|
return PCOL_PENTAIR;
|
||||||
|
|
||||||
|
return PCOL_UNKNOWN;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLAYBACK_MODE
|
||||||
|
/*
|
||||||
|
Open and Initialize the serial communications port to the Aqualink RS8 device.
|
||||||
|
Arg is tty or port designation string
|
||||||
|
returns the file descriptor
|
||||||
|
*/
|
||||||
|
int init_serial_port(const char* tty)
|
||||||
|
{
|
||||||
|
long BAUD = B9600;
|
||||||
|
long DATABITS = CS8;
|
||||||
|
long STOPBITS = 0;
|
||||||
|
long PARITYON = 0;
|
||||||
|
long PARITY = 0;
|
||||||
|
|
||||||
|
struct termios newtio; //place for old and new port settings for serial port
|
||||||
|
|
||||||
|
//int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
|
int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
|
||||||
|
if (fd < 0) {
|
||||||
|
logMessage(LOG_ERR, "Unable to open port: %s\n", tty);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
logMessage(LOG_DEBUG_SERIAL, "Openeded serial port %s\n",tty);
|
||||||
|
|
||||||
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK | O_NDELAY);
|
||||||
|
newtio.c_cc[VMIN]= 0;
|
||||||
|
newtio.c_cc[VTIME]= 1;
|
||||||
|
logMessage(LOG_DEBUG_SERIAL, "Set serial port %s to non blocking mode\n",tty);
|
||||||
|
|
||||||
|
tcgetattr(fd, &_oldtio); // save current port settings
|
||||||
|
// set new port settings for canonical input processing
|
||||||
|
newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
|
||||||
|
newtio.c_iflag = IGNPAR;
|
||||||
|
newtio.c_lflag = 0; // ICANON;
|
||||||
|
newtio.c_oflag = 0;
|
||||||
|
|
||||||
|
tcflush(fd, TCIFLUSH);
|
||||||
|
tcsetattr(fd, TCSANOW, &newtio);
|
||||||
|
|
||||||
|
logMessage(LOG_DEBUG_SERIAL, "Set serial port %s io attributes\n",tty);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close tty port */
|
||||||
|
void close_serial_port(int fd)
|
||||||
|
{
|
||||||
|
tcsetattr(fd, TCSANOW, &_oldtio);
|
||||||
|
close(fd);
|
||||||
|
logMessage(LOG_DEBUG_SERIAL, "Closed serial port\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Send an ack packet to the Aqualink RS8 master device.
|
||||||
|
// fd: the file descriptor of the serial port connected to the device
|
||||||
|
// command: the command byte to send to the master device, NUL if no command
|
||||||
|
//
|
||||||
|
// NUL = '\x00'
|
||||||
|
// DLE = '\x10'
|
||||||
|
// STX = '\x02'
|
||||||
|
// ETX = '\x03'
|
||||||
|
//
|
||||||
|
// masterAddr = '\x00' # address of Aqualink controller
|
||||||
|
//
|
||||||
|
//msg = DLE+STX+dest+cmd+args
|
||||||
|
//msg = msg+self.checksum(msg)+DLE+ETX
|
||||||
|
// DLE+STX+DEST+CMD+ARGS+CHECKSUM+DLE+ETX
|
||||||
|
|
||||||
|
|
||||||
|
void print_hex(char *pk, int length)
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
for (i=0;i<length;i++)
|
||||||
|
{
|
||||||
|
printf("0x%02hhx|",pk[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void test_cmd()
|
||||||
|
{
|
||||||
|
const int length = 11;
|
||||||
|
unsigned char ackPacket[] = { NUL, DLE, STX, DEV_MASTER, CMD_ACK, NUL, NUL, 0x13, DLE, ETX, NUL };
|
||||||
|
//send_cmd(fd, CMD_ACK, command);
|
||||||
|
|
||||||
|
print_hex((char *)ackPacket, length);
|
||||||
|
|
||||||
|
ackPacket[7] = generate_checksum(ackPacket, length-1);
|
||||||
|
print_hex((char *)ackPacket, length);
|
||||||
|
|
||||||
|
ackPacket[6] = 0x02;
|
||||||
|
ackPacket[7] = generate_checksum(ackPacket, length-1);
|
||||||
|
print_hex((char *)ackPacket, length);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
void send_test_cmd(int fd, unsigned char destination, unsigned char b1, unsigned char b2, unsigned char b3)
|
||||||
|
{
|
||||||
|
const int length = 11;
|
||||||
|
unsigned char ackPacket[] = { NUL, DLE, STX, DEV_MASTER, CMD_ACK, NUL, NUL, 0x13, DLE, ETX, NUL };
|
||||||
|
//unsigned char ackPacket[] = { NUL, DLE, STX, DEV_MASTER, NUL, NUL, NUL, 0x13, DLE, ETX, NUL };
|
||||||
|
|
||||||
|
// Update the packet and checksum if command argument is not NUL.
|
||||||
|
ackPacket[3] = destination;
|
||||||
|
ackPacket[4] = b1;
|
||||||
|
ackPacket[5] = b2;
|
||||||
|
ackPacket[6] = b3;
|
||||||
|
ackPacket[7] = generate_checksum(ackPacket, length-1);
|
||||||
|
|
||||||
|
#ifdef BLOCKING_MODE
|
||||||
|
write(fd, ackPacket, length);
|
||||||
|
#else
|
||||||
|
int nwrite, i;
|
||||||
|
for (i=0; i<length; i += nwrite) {
|
||||||
|
nwrite = write(fd, ackPacket + i, length - i);
|
||||||
|
if (nwrite < 0)
|
||||||
|
logMessage(LOG_ERR, "write to serial port failed\n");
|
||||||
|
}
|
||||||
|
//logMessage(LOG_DEBUG_SERIAL, "Send %d bytes to serial\n",length);
|
||||||
|
//tcdrain(fd);
|
||||||
|
//logMessage(LOG_DEBUG, "Send '0x%02hhx' to '0x%02hhx'\n", command, destination);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
log_packet("Sent ", ackPacket, length);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
unsigned char tp[] = {PCOL_PENTAIR, 0x07, 0x0F, 0x10, 0x08, 0x0D, 0x55, 0x55, 0x5B, 0x2A, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00};
|
||||||
|
send_command(0, tp, 19);
|
||||||
|
Should produce
|
||||||
|
{0xFF, 0x00, 0xFF, 0xA5, 0x07, 0x0F, 0x10, 0x08, 0x0D, 0x55, 0x55, 0x5B, 0x2A, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x02, 0x9E};
|
||||||
|
<------- headder ----> <-- type to from type-> <len> <------------------------------ data ----------------------------------------> <checksum>
|
||||||
|
*/
|
||||||
|
|
||||||
|
void send_pentair_command(int fd, unsigned char *packet_buffer, int size)
|
||||||
|
{
|
||||||
|
unsigned char packet[AQ_MAXPKTLEN];
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
packet[0] = NUL;
|
||||||
|
packet[1] = PP1;
|
||||||
|
packet[2] = PP2;
|
||||||
|
packet[3] = PP3;
|
||||||
|
packet[4] = PP4;
|
||||||
|
|
||||||
|
//packet[i++] = 0x00; // from
|
||||||
|
//packet[i++] = // to
|
||||||
|
for (i=5; i-4 < size; i++) {
|
||||||
|
//printf("added 0x%02hhx at position %d\n",packet_buffer[i-4],i);
|
||||||
|
if (i==6) {
|
||||||
|
// Replace source
|
||||||
|
packet[i] = 0x00;
|
||||||
|
} else if (i==9) {
|
||||||
|
// Replace length
|
||||||
|
//packet[i] = 0xFF;
|
||||||
|
packet[i] = (unsigned char)size-6;
|
||||||
|
} else {
|
||||||
|
packet[i] = packet_buffer[i-4];
|
||||||
|
}
|
||||||
|
|
||||||
|
//packet[i] = packet_buffer[i-4];
|
||||||
|
}
|
||||||
|
|
||||||
|
packet[++i] = NUL; // Checksum
|
||||||
|
packet[++i] = NUL; // Checksum
|
||||||
|
generate_pentair_checksum(&packet[1], i);
|
||||||
|
packet[++i] = NUL;
|
||||||
|
|
||||||
|
|
||||||
|
//logPacket(packet, i);
|
||||||
|
send_packet(fd,packet,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//unsigned char packet_buffer[] = {PCOL_PENTAIR, 0x07, 0x0F, 0x10, 0x08, 0x0D, 0x55, 0x55, 0x5B, 0x2A, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00};
|
||||||
|
//unsigned char packet_buffer[] = {PCOL_JANDY, 0x07, 0x0F, 0x00, 0x00};
|
||||||
|
void send_command(int fd, unsigned char *packet_buffer, int size)
|
||||||
|
{
|
||||||
|
unsigned char packet[AQ_MAXPKTLEN];
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
if (packet_buffer[0] != PCOL_JANDY) {
|
||||||
|
//logMessage(LOG_ERR, "Only Jandy protocol supported at present!\n");
|
||||||
|
send_pentair_command(fd, packet_buffer, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet[0] = NUL;
|
||||||
|
packet[1] = DLE;
|
||||||
|
packet[2] = STX;
|
||||||
|
|
||||||
|
for (i=3; i-2 < size; i++) {
|
||||||
|
//printf("added 0x%02hhx at position %d\n",packet_buffer[i-2],i);
|
||||||
|
packet[i] = packet_buffer[i-2];
|
||||||
|
}
|
||||||
|
|
||||||
|
packet[++i] = DLE;
|
||||||
|
packet[++i] = ETX;
|
||||||
|
packet[++i] = NUL;
|
||||||
|
|
||||||
|
packet[i-3] = generate_checksum(packet, i);
|
||||||
|
|
||||||
|
send_packet(fd,packet,++i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_packet(int fd, unsigned char *packet, int length)
|
||||||
|
{
|
||||||
|
|
||||||
|
int nwrite, i;
|
||||||
|
for (i=0; i<length; i += nwrite) {
|
||||||
|
nwrite = write(fd, packet + i, length - i);
|
||||||
|
if (nwrite < 0)
|
||||||
|
logMessage(LOG_ERR, "write to serial port failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getLogLevel() >= LOG_DEBUG_SERIAL) {
|
||||||
|
//char buf[30];
|
||||||
|
//sprintf(buf, "Sent %8.8s ", get_packet_type(packet+1, length));
|
||||||
|
//log_packet(buf, packet, length);
|
||||||
|
logPacket(packet, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _send_ack(int fd, unsigned char ack_type, unsigned char command)
|
||||||
|
{
|
||||||
|
const int length = 11;
|
||||||
|
// Default null ack with checksum generated, don't mess with it, just over right
|
||||||
|
unsigned char ackPacket[] = { NUL, DLE, STX, DEV_MASTER, CMD_ACK, NUL, NUL, 0x13, DLE, ETX, NUL };
|
||||||
|
|
||||||
|
// Update the packet and checksum if command argument is not NUL.
|
||||||
|
if(command != NUL || ack_type != NUL) {
|
||||||
|
//ackPacket[5] = 0x00 normal, 0x03 some pause, 0x01 some pause ending (0x01 = Screen Busy (also return from logn message))
|
||||||
|
ackPacket[5] = ack_type;
|
||||||
|
ackPacket[6] = command;
|
||||||
|
ackPacket[7] = generate_checksum(ackPacket, length-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
send_packet(fd, ackPacket, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_ack(int fd, unsigned char command)
|
||||||
|
{
|
||||||
|
_send_ack(fd, ACK_NORMAL, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ack_typ should only be ACK_PDA, ACK_NORMAL, ACK_SCREEN_BUSY, ACK_SCREEN_BUSY_DISPLAY
|
||||||
|
void send_extended_ack(int fd, unsigned char ack_type, unsigned char command)
|
||||||
|
{
|
||||||
|
_send_ack(fd, ack_type, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _get_packet(int fd, unsigned char* packet, bool rawlog);
|
||||||
|
|
||||||
|
int get_packet(int fd, unsigned char* packet)
|
||||||
|
{
|
||||||
|
return _get_packet(fd, packet, false);
|
||||||
|
}
|
||||||
|
int get_packet_lograw(int fd, unsigned char* packet)
|
||||||
|
{
|
||||||
|
return _get_packet(fd, packet, true);
|
||||||
|
}
|
||||||
|
int _get_packet(int fd, unsigned char* packet, bool rawlog)
|
||||||
|
{
|
||||||
|
unsigned char byte;
|
||||||
|
int bytesRead;
|
||||||
|
int index = 0;
|
||||||
|
bool endOfPacket = false;
|
||||||
|
//bool packetStarted = FALSE;
|
||||||
|
bool lastByteDLE = false;
|
||||||
|
int retry = 0;
|
||||||
|
bool jandyPacketStarted = false;
|
||||||
|
bool pentairPacketStarted = false;
|
||||||
|
//bool lastByteDLE = false;
|
||||||
|
int PentairPreCnt = 0;
|
||||||
|
int PentairDataCnt = -1;
|
||||||
|
|
||||||
|
// Read packet in byte order below
|
||||||
|
// DLE STX ........ ETX DLE
|
||||||
|
// sometimes we get ETX DLE and no start, so for now just ignoring that. Seem to be more applicable when busy RS485 traffic
|
||||||
|
|
||||||
|
while (!endOfPacket) {
|
||||||
|
bytesRead = read(fd, &byte, 1);
|
||||||
|
//if (bytesRead < 0 && errno == EAGAIN && packetStarted == FALSE && lastByteDLE == FALSE) {
|
||||||
|
if (bytesRead < 0 && errno == EAGAIN &&
|
||||||
|
jandyPacketStarted == false &&
|
||||||
|
pentairPacketStarted == false &&
|
||||||
|
lastByteDLE == false) {
|
||||||
|
// We just have nothing to read
|
||||||
|
return 0;
|
||||||
|
} else if (bytesRead < 0 && errno == EAGAIN) {
|
||||||
|
// If we are in the middle of reading a packet, keep going
|
||||||
|
if (retry > 20) {
|
||||||
|
logMessage(LOG_WARNING, "Serial read timeout\n");
|
||||||
|
//log_packet(LOG_WARNING, "Bad receive packet ", packet, index);
|
||||||
|
logPacketError(packet, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
retry++;
|
||||||
|
delay(10);
|
||||||
|
#ifdef TESTING
|
||||||
|
} else if (bytesRead == 0 && jandyPacketStarted == false && pentairPacketStarted == false) {
|
||||||
|
// Probably set port to /dev/null for testing.
|
||||||
|
//printf("Read loop return\n");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
} else if (bytesRead == 1) {
|
||||||
|
if (rawlog)
|
||||||
|
logPacketByte(&byte);
|
||||||
|
|
||||||
|
if (lastByteDLE == true && byte == NUL)
|
||||||
|
{
|
||||||
|
// Check for DLE | NULL (that's escape DLE so delete the NULL)
|
||||||
|
//printf("IGNORE THIS PACKET\n");
|
||||||
|
lastByteDLE = false;
|
||||||
|
}
|
||||||
|
else if (lastByteDLE == true)
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
index++;
|
||||||
|
|
||||||
|
packet[index] = byte;
|
||||||
|
index++;
|
||||||
|
if (byte == STX && jandyPacketStarted == false)
|
||||||
|
{
|
||||||
|
jandyPacketStarted = true;
|
||||||
|
pentairPacketStarted = false;
|
||||||
|
}
|
||||||
|
else if (byte == ETX && jandyPacketStarted == true)
|
||||||
|
{
|
||||||
|
endOfPacket = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (jandyPacketStarted || pentairPacketStarted)
|
||||||
|
{
|
||||||
|
packet[index] = byte;
|
||||||
|
index++;
|
||||||
|
if (pentairPacketStarted == true && index == 9)
|
||||||
|
{
|
||||||
|
//printf("Read 0x%02hhx %d pentair\n", byte, byte);
|
||||||
|
PentairDataCnt = byte;
|
||||||
|
}
|
||||||
|
if (PentairDataCnt >= 0 && index - 11 >= PentairDataCnt && pentairPacketStarted == true)
|
||||||
|
{
|
||||||
|
endOfPacket = true;
|
||||||
|
PentairPreCnt = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (byte == DLE && jandyPacketStarted == false)
|
||||||
|
{
|
||||||
|
packet[index] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // reset index incase we have EOP before start
|
||||||
|
if (jandyPacketStarted == false && pentairPacketStarted == false)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byte == DLE && pentairPacketStarted == false)
|
||||||
|
{
|
||||||
|
lastByteDLE = true;
|
||||||
|
PentairPreCnt = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastByteDLE = false;
|
||||||
|
if (byte == PP1 && PentairPreCnt == 0)
|
||||||
|
PentairPreCnt = 1;
|
||||||
|
else if (byte == PP2 && PentairPreCnt == 1)
|
||||||
|
PentairPreCnt = 2;
|
||||||
|
else if (byte == PP3 && PentairPreCnt == 2)
|
||||||
|
PentairPreCnt = 3;
|
||||||
|
else if (byte == PP4 && PentairPreCnt == 3)
|
||||||
|
{
|
||||||
|
pentairPacketStarted = true;
|
||||||
|
jandyPacketStarted = false;
|
||||||
|
PentairDataCnt = -1;
|
||||||
|
packet[0] = PP1;
|
||||||
|
packet[1] = PP2;
|
||||||
|
packet[2] = PP3;
|
||||||
|
packet[3] = byte;
|
||||||
|
index = 4;
|
||||||
|
}
|
||||||
|
else if (byte != PP1) // Don't reset counter if multiple PP1's
|
||||||
|
PentairPreCnt = 0;
|
||||||
|
}
|
||||||
|
} else if(bytesRead < 0) {
|
||||||
|
// Got a read error. Wait one millisecond for the next byte to
|
||||||
|
// arrive.
|
||||||
|
logMessage(LOG_WARNING, "Read error: %d - %s\n", errno, strerror(errno));
|
||||||
|
if(errno == 9) {
|
||||||
|
// Bad file descriptor. Port has been disconnected for some reason.
|
||||||
|
// Return a -1.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break out of the loop if we exceed maximum packet
|
||||||
|
// length.
|
||||||
|
if (index >= AQ_MAXPKTLEN) {
|
||||||
|
logPacketError(packet, index);
|
||||||
|
logMessage(LOG_WARNING, "Serial packet too large\n");
|
||||||
|
//log_packet(LOG_WARNING, "Bad receive packet ", packet, index);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//logMessage(LOG_DEBUG, "Serial checksum, length %d got 0x%02hhx expected 0x%02hhx\n", index, packet[index-3], generate_checksum(packet, index));
|
||||||
|
if (jandyPacketStarted) {
|
||||||
|
if (check_jandy_checksum(packet, index) != true){
|
||||||
|
logPacketError(packet, index);
|
||||||
|
logMessage(LOG_WARNING, "Serial read bad Jandy checksum, ignoring\n");
|
||||||
|
//log_packet(LOG_WARNING, "Bad receive packet ", packet, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (pentairPacketStarted) {
|
||||||
|
if (check_pentair_checksum(packet, index) != true){
|
||||||
|
logPacketError(packet, index);
|
||||||
|
logMessage(LOG_WARNING, "Serial read bad Pentair checksum, ignoring\n");
|
||||||
|
//log_packet(LOG_WARNING, "Bad receive packet ", packet, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (generate_checksum(packet, index) != packet[index-3]){
|
||||||
|
logMessage(LOG_WARNING, "Serial read bad checksum, ignoring\n");
|
||||||
|
log_packet(LOG_WARNING, "Bad receive packet ", packet, index);
|
||||||
|
return 0;
|
||||||
|
} else*/ if (index < AQ_MINPKTLEN && (jandyPacketStarted || pentairPacketStarted) ) { //NSF. Sometimes we get END sequence only, so just ignore.
|
||||||
|
logPacketError(packet, index);
|
||||||
|
logMessage(LOG_WARNING, "Serial read too small\n");
|
||||||
|
//log_packet(LOG_WARNING, "Bad receive packet ", packet, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
logMessage(LOG_DEBUG_SERIAL, "Serial read %d bytes\n",index);
|
||||||
|
logPacket(packet, index);
|
||||||
|
// Return the packet length.
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // PLAYBACKMODE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else //USE_AQ_SERIAL_OLD
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//#define BLOCKING_MODE
|
//#define BLOCKING_MODE
|
||||||
#define PENTAIR_LENGTH_FIX
|
|
||||||
|
|
||||||
static struct termios _oldtio;
|
static struct termios _oldtio;
|
||||||
|
|
||||||
|
@ -77,21 +707,6 @@ void log_packet(int level, char *init_str, unsigned char* packet, int length)
|
||||||
//logMessage(LOG_DEBUG_SERIAL, buff);
|
//logMessage(LOG_DEBUG_SERIAL, buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* get_packet_type(unsigned char* packet , int length)
|
const char* get_packet_type(unsigned char* packet , int length)
|
||||||
{
|
{
|
||||||
static char buf[15];
|
static char buf[15];
|
||||||
|
@ -586,6 +1201,34 @@ bool check_jandy_checksum(unsigned char* packet, int length)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_pentair_checksum(unsigned char* packet, int length)
|
bool check_pentair_checksum(unsigned char* packet, int length)
|
||||||
|
{
|
||||||
|
//printf("check_pentair_checksum \n");
|
||||||
|
int i, sum, n;
|
||||||
|
n = packet[8] + 9;
|
||||||
|
//n = packet[8] + 8;
|
||||||
|
sum = 0;
|
||||||
|
for (i = 3; i < n; i++) {
|
||||||
|
//printf("Sum 0x%02hhx\n",packet[i]);
|
||||||
|
sum += (int) packet[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("Check High 0x%02hhx = 0x%02hhx = 0x%02hhx\n",packet[n], packet[length-2],((sum >> 8) & 0xFF) );
|
||||||
|
//printf("Check Low 0x%02hhx = 0x%02hhx = 0x%02hhx\n",packet[n + 1], packet[length-1], (sum & 0xFF) );
|
||||||
|
|
||||||
|
// Check against caculated length
|
||||||
|
if (sum == (packet[length-2] * 256 + packet[length-1]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check against actual # length
|
||||||
|
if (sum == (packet[n] * 256 + packet[n+1])) {
|
||||||
|
//logMessage(LOG_ERR, "Pentair checksum is accurate but length is not\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
bool check_pentair_checksum_old(unsigned char* packet, int length)
|
||||||
{
|
{
|
||||||
int i, sum, n;
|
int i, sum, n;
|
||||||
n = packet[8] + 9;
|
n = packet[8] + 9;
|
||||||
|
@ -594,17 +1237,12 @@ bool check_pentair_checksum(unsigned char* packet, int length)
|
||||||
sum += (int) packet[i];
|
sum += (int) packet[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PENTAIR_LENGTH_FIX
|
|
||||||
if (sum == (packet[length-1] * 256 + packet[length]))
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
if (sum == (packet[length-2] * 256 + packet[length-1]))
|
if (sum == (packet[length-2] * 256 + packet[length-1]))
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
int _get_packet(int fd, unsigned char* packet, bool rawlog);
|
int _get_packet(int fd, unsigned char* packet, bool rawlog);
|
||||||
|
|
||||||
int get_packet_new_lograw(int fd, unsigned char* packet)
|
int get_packet_new_lograw(int fd, unsigned char* packet)
|
||||||
|
@ -693,9 +1331,6 @@ int _get_packet(int fd, unsigned char* packet, bool rawlog)
|
||||||
{
|
{
|
||||||
endOfPacket = true;
|
endOfPacket = true;
|
||||||
PentairPreCnt = -1;
|
PentairPreCnt = -1;
|
||||||
#ifndef PENTAIR_LENGTH_FIX
|
|
||||||
index--;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (byte == DLE && jandyPacketStarted == false)
|
else if (byte == DLE && jandyPacketStarted == false)
|
||||||
|
@ -1020,3 +1655,5 @@ int get_packet_old(int fd, unsigned char* packet)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // USE_OLD
|
||||||
|
|
||||||
|
|
14
aq_serial.h
14
aq_serial.h
|
@ -6,6 +6,13 @@
|
||||||
|
|
||||||
#define CONNECTION_ERROR "ERROR No connection to RS control panel"
|
#define CONNECTION_ERROR "ERROR No connection to RS control panel"
|
||||||
|
|
||||||
|
|
||||||
|
// Protocol types
|
||||||
|
#define PCOL_JANDY 0xFF
|
||||||
|
#define PCOL_PENTAIR 0xFE
|
||||||
|
#define PCOL_UNKNOWN 0xFD
|
||||||
|
|
||||||
|
|
||||||
// packet offsets
|
// packet offsets
|
||||||
#define PKT_DEST 2
|
#define PKT_DEST 2
|
||||||
#define PKT_CMD 3
|
#define PKT_CMD 3
|
||||||
|
@ -205,7 +212,8 @@ SPILLOVER IS DISABLED WHILE SPA IS ON
|
||||||
#define SWG_STATUS_CHECK_PCB 0x80 // check PCB 0x80
|
#define SWG_STATUS_CHECK_PCB 0x80 // check PCB 0x80
|
||||||
|
|
||||||
|
|
||||||
#define CMD_PDA_0x05 0x05
|
#define CMD_PDA_0x04 0x04 // No idea, might be building menu
|
||||||
|
#define CMD_PDA_0x05 0x05 // No idea
|
||||||
#define CMD_PDA_0x1B 0x1b
|
#define CMD_PDA_0x1B 0x1b
|
||||||
#define CMD_PDA_HIGHLIGHT 0x08
|
#define CMD_PDA_HIGHLIGHT 0x08
|
||||||
#define CMD_PDA_CLEAR 0x09
|
#define CMD_PDA_CLEAR 0x09
|
||||||
|
@ -245,7 +253,7 @@ typedef enum {
|
||||||
} protocolType;
|
} protocolType;
|
||||||
|
|
||||||
|
|
||||||
int init_serial_port(char* tty);
|
int init_serial_port(const char* tty);
|
||||||
void close_serial_port(int file_descriptor);
|
void close_serial_port(int file_descriptor);
|
||||||
void set_pda_mode(bool mode);
|
void set_pda_mode(bool mode);
|
||||||
bool pda_mode();
|
bool pda_mode();
|
||||||
|
@ -257,6 +265,8 @@ void send_ack(int file_descriptor, unsigned char command);
|
||||||
void send_extended_ack(int fd, unsigned char ack_type, unsigned char command);
|
void send_extended_ack(int fd, unsigned char ack_type, unsigned char command);
|
||||||
//void send_cmd(int file_descriptor, unsigned char cmd, unsigned char args);
|
//void send_cmd(int file_descriptor, unsigned char cmd, unsigned char args);
|
||||||
int get_packet(int file_descriptor, unsigned char* packet);
|
int get_packet(int file_descriptor, unsigned char* packet);
|
||||||
|
int get_packet_lograw(int fd, unsigned char* packet);
|
||||||
|
|
||||||
int get_packet_new(int fd, unsigned char* packet);
|
int get_packet_new(int fd, unsigned char* packet);
|
||||||
int get_packet_new_lograw(int fd, unsigned char* packet);
|
int get_packet_new_lograw(int fd, unsigned char* packet);
|
||||||
//void close_serial_port(int file_descriptor, struct termios* oldtio);
|
//void close_serial_port(int file_descriptor, struct termios* oldtio);
|
||||||
|
|
13
aqualinkd.c
13
aqualinkd.c
|
@ -1010,10 +1010,11 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer) {
|
||||||
if (_config_parameters.pda_sleep_mode && pda_shouldSleep()) {
|
if (_config_parameters.pda_sleep_mode && pda_shouldSleep()) {
|
||||||
logMessage(LOG_DEBUG, "PDA Aqualink daemon in sleep mode\n");
|
logMessage(LOG_DEBUG, "PDA Aqualink daemon in sleep mode\n");
|
||||||
return;
|
return;
|
||||||
} else if (packet_buffer[PKT_CMD] != CMD_STATUS)
|
//} else if (packet_buffer[PKT_CMD] != CMD_STATUS) // Moved logic to pop_aq_cmd()
|
||||||
send_ack(rs_fd, NUL);
|
// send_extended_ack(rs_fd, ACK_PDA, NUL);
|
||||||
else
|
} else {
|
||||||
send_ack(rs_fd, pop_aq_cmd(&_aqualink_data));
|
send_extended_ack(rs_fd, ACK_PDA, pop_aq_cmd(&_aqualink_data));
|
||||||
|
}
|
||||||
|
|
||||||
} else if (_aqualink_data.simulate_panel && _aqualink_data.active_thread.thread_id == 0) {
|
} else if (_aqualink_data.simulate_panel && _aqualink_data.active_thread.thread_id == 0) {
|
||||||
// We are in simlator mode, ack get's complicated now.
|
// We are in simlator mode, ack get's complicated now.
|
||||||
|
@ -1171,9 +1172,7 @@ void main_loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config_parameters.log_raw_RS_bytes)
|
if (_config_parameters.log_raw_RS_bytes)
|
||||||
packet_length = get_packet_new_lograw(rs_fd, packet_buffer);
|
packet_length = get_packet_lograw(rs_fd, packet_buffer);
|
||||||
else if (_config_parameters.read_pentair_packets)
|
|
||||||
packet_length = get_packet_new(rs_fd, packet_buffer);
|
|
||||||
else
|
else
|
||||||
packet_length = get_packet(rs_fd, packet_buffer);
|
packet_length = get_packet(rs_fd, packet_buffer);
|
||||||
|
|
||||||
|
|
72
log_reader.c
72
log_reader.c
|
@ -22,6 +22,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "aq_serial.h"
|
#include "aq_serial.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -49,6 +52,41 @@ void logiAqualinkMsg(unsigned char *packet_buffer, int packet_length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void read_bin_file(char *filename)
|
||||||
|
{
|
||||||
|
unsigned char packet_buffer[AQ_MAXPKTLEN];
|
||||||
|
int packet_length;
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
setLoggingPrms(LOG_DEBUG_SERIAL , false, NULL, NULL);
|
||||||
|
startPacketLogger(false,true);
|
||||||
|
|
||||||
|
int fd = open(filename, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
|
||||||
|
if (fd < 0) {
|
||||||
|
logMessage(LOG_ERR, "Unable to open port: %s\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( (packet_length = get_packet_new(fd, packet_buffer)) > -1){
|
||||||
|
printf("----------------\n");
|
||||||
|
//logPacket(packet_buffer, packet_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_bin_file(FILE *in, FILE *out) {
|
||||||
|
char hex[6];
|
||||||
|
unsigned char byte;
|
||||||
|
|
||||||
|
while ( fgets ( hex, 6, in ) != NULL ) /* read a line */
|
||||||
|
{
|
||||||
|
byte = (int)strtol(hex, NULL, 16);
|
||||||
|
//printf("read 0x%02hhx, %s\n",byte,hex);
|
||||||
|
fwrite(&byte, 1,1, out);
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
//unsigned char packet_buffer[10];
|
//unsigned char packet_buffer[10];
|
||||||
|
@ -56,14 +94,31 @@ int main(int argc, char *argv[]) {
|
||||||
int packet_length = 0;
|
int packet_length = 0;
|
||||||
char hex[5];
|
char hex[5];
|
||||||
int i;
|
int i;
|
||||||
|
FILE *outfile = NULL;
|
||||||
|
bool writeb = false;
|
||||||
//int num;
|
//int num;
|
||||||
//int pi;
|
//int pi;
|
||||||
|
|
||||||
if (argc < 1 || access( argv[1], F_OK ) == -1 ) {
|
if (strcmp(argv[1], "-rb") == 0) {
|
||||||
|
read_bin_file(argv[2]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (argc < 1 || access( argv[1], F_OK ) == -1 ) {
|
||||||
fprintf(stderr, "ERROR, first param must be valid log file\n");
|
fprintf(stderr, "ERROR, first param must be valid log file\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (strcmp(argv[2], "-b") == 0) {
|
||||||
|
outfile = fopen ( argv[3], "w" );
|
||||||
|
if ( outfile == NULL )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR, Couldn't open out file `%s`\n", argv[3]);
|
||||||
|
perror ( argv[3] ); /* why didn't the file open? */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
writeb = true;
|
||||||
|
}
|
||||||
|
|
||||||
FILE *file = fopen ( argv[1], "r" );
|
FILE *file = fopen ( argv[1], "r" );
|
||||||
if ( file == NULL )
|
if ( file == NULL )
|
||||||
{
|
{
|
||||||
|
@ -71,6 +126,13 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (writeb) {
|
||||||
|
create_bin_file(file, outfile);
|
||||||
|
fclose ( file );
|
||||||
|
fclose ( outfile );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char line [ 128 ]; /* or other suitable maximum line size */
|
char line [ 128 ]; /* or other suitable maximum line size */
|
||||||
while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
|
while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
|
||||||
{
|
{
|
||||||
|
@ -85,20 +147,22 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
packet_length--;
|
packet_length--;
|
||||||
|
|
||||||
|
|
||||||
if (packet_buffer[PKT_DEST] == 0x33 && packet_buffer[PKT_CMD] == 0x25)
|
if (packet_buffer[PKT_DEST] == 0x33 && packet_buffer[PKT_CMD] == 0x25)
|
||||||
logiAqualinkMsg(packet_buffer, packet_length);
|
logiAqualinkMsg(packet_buffer, packet_length);
|
||||||
|
|
||||||
//if (packet_buffer[PKT_CMD] == 0x24 || packet_buffer[PKT_CMD] == 0x25) {
|
//if (packet_buffer[PKT_CMD] == 0x24 || packet_buffer[PKT_CMD] == 0x25) {
|
||||||
|
|
||||||
printf("To 0x%02hhx, type %15.15s, length %2.2d ", packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length),packet_length);
|
printf("To 0x%02hhx, type %15.15s, length %2.2d\n", packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length),packet_length);
|
||||||
fputs ( line, stdout );
|
fputs ( line, stdout );
|
||||||
//printf("Message : '");
|
//printf("Message : '");
|
||||||
//fwrite(packet_buffer + 4, 1, packet_length-7, stdout);
|
//fwrite(packet_buffer + 4, 1, packet_length-7, stdout);
|
||||||
//printf("'\n");
|
//printf("'\n");
|
||||||
//}
|
//}
|
||||||
}
|
|
||||||
fclose ( file );
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose ( file );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,16 +156,25 @@ bool loopover_devices(struct aqualinkdata *aq_data) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if charlimit is set, use case insensitive match and limit chars.
|
if charlimit is set, use case insensitive match and limit chars.
|
||||||
|
if charlimit is -1, use VERY loose matching.
|
||||||
*/
|
*/
|
||||||
bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charlimit) {
|
bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charlimit) {
|
||||||
int i=pda_m_hlightindex();
|
int i=pda_m_hlightindex();
|
||||||
int min_index = -1;
|
int min_index = -1;
|
||||||
int max_index = -1;
|
int max_index = -1;
|
||||||
|
int index = -1;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
logMessage(LOG_DEBUG, "PDA Device programmer looking for menu text '%s'\n",menuText);
|
logMessage(LOG_DEBUG, "PDA Device programmer looking for menu text '%s'\n",menuText);
|
||||||
|
|
||||||
int index = (charlimit == 0)?pda_find_m_index(menuText):pda_find_m_index_case(menuText, charlimit);
|
if (charlimit == 0)
|
||||||
|
index = pda_find_m_index(menuText);
|
||||||
|
else if (charlimit > 0)
|
||||||
|
index = pda_find_m_index_case(menuText, charlimit);
|
||||||
|
else if (charlimit == -1)
|
||||||
|
index = pda_find_m_index_loose(menuText);
|
||||||
|
|
||||||
|
//int index = (charlimit == 0)?pda_find_m_index(menuText):pda_find_m_index_case(menuText, charlimit);
|
||||||
|
|
||||||
if (index < 0) { // No menu, is there a page down. "PDA Line 9 = ^^ MORE __"
|
if (index < 0) { // No menu, is there a page down. "PDA Line 9 = ^^ MORE __"
|
||||||
if (strncasecmp(pda_m_line(9)," ^^ MORE", 10) == 0) {
|
if (strncasecmp(pda_m_line(9)," ^^ MORE", 10) == 0) {
|
||||||
|
@ -267,9 +276,18 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli
|
||||||
return waitForPDAMessageHighlight(aq_data, index, 10);
|
return waitForPDAMessageHighlight(aq_data, index, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu) {
|
bool _select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu, bool loose);
|
||||||
|
|
||||||
if ( find_pda_menu_item(aq_data, menuText, 0) ) {
|
bool select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu){
|
||||||
|
return _select_pda_menu_item(aq_data, menuText, waitForNextMenu, false);
|
||||||
|
}
|
||||||
|
bool select_pda_menu_item_loose(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu){
|
||||||
|
return _select_pda_menu_item(aq_data, menuText, waitForNextMenu, true);
|
||||||
|
}
|
||||||
|
bool _select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu, bool loose) {
|
||||||
|
|
||||||
|
int matchType = loose?-1:0;
|
||||||
|
if ( find_pda_menu_item(aq_data, menuText, matchType) ) {
|
||||||
send_cmd(KEY_PDA_SELECT);
|
send_cmd(KEY_PDA_SELECT);
|
||||||
|
|
||||||
logMessage(LOG_DEBUG, "PDA Device programmer selected menu item '%s'\n",menuText);
|
logMessage(LOG_DEBUG, "PDA Device programmer selected menu item '%s'\n",menuText);
|
||||||
|
@ -386,6 +404,17 @@ bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) {
|
||||||
ret = waitForPDAnextMenu(aq_data);
|
ret = waitForPDAnextMenu(aq_data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PM_BOOST:
|
||||||
|
if (pda_m_type() == PM_HOME) {
|
||||||
|
ret = select_pda_menu_item(aq_data, "MENU", true);
|
||||||
|
} else if (pda_m_type() == PM_MAIN) {
|
||||||
|
ret = select_pda_menu_item_loose(aq_data, "BOOST", true);
|
||||||
|
} else {
|
||||||
|
send_cmd(KEY_PDA_BACK);
|
||||||
|
ret = waitForPDAnextMenu(aq_data);
|
||||||
|
}
|
||||||
|
//printf("****MENU SELECT RETURN %d*****\n",ret);
|
||||||
|
break;
|
||||||
case PM_SET_TEMP:
|
case PM_SET_TEMP:
|
||||||
if (pda_m_type() == PM_HOME) {
|
if (pda_m_type() == PM_HOME) {
|
||||||
ret = select_pda_menu_item(aq_data, "MENU", true);
|
ret = select_pda_menu_item(aq_data, "MENU", true);
|
||||||
|
@ -421,8 +450,7 @@ bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) {
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
logMessage(LOG_DEBUG, "PDA Device programmer request for menu %d, current %d\n",
|
logMessage(LOG_DEBUG, "PDA Device programmer request for menu %d, current %d\n", menu, pda_m_type());
|
||||||
menu, pda_m_type());
|
|
||||||
}
|
}
|
||||||
if (pda_m_type() != menu) {
|
if (pda_m_type() != menu) {
|
||||||
logMessage(LOG_ERR, "PDA Device programmer didn't find a requested menu %d, current %d\n", menu, pda_m_type());
|
logMessage(LOG_ERR, "PDA Device programmer didn't find a requested menu %d, current %d\n", menu, pda_m_type());
|
||||||
|
@ -812,6 +840,49 @@ bool set_PDA_aqualink_SWG_setpoint(struct aqualinkdata *aq_data, int val) {
|
||||||
//return true;
|
//return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool set_PDA_aqualink_boost(struct aqualinkdata *aq_data, bool val)
|
||||||
|
{
|
||||||
|
if (! goto_pda_menu(aq_data, PM_BOOST)) {
|
||||||
|
logMessage(LOG_ERR, "Error finding BOOST menu\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Should be on the START menu item
|
||||||
|
if (val == true) { // Turn on should just be enter
|
||||||
|
if (strstr(pda_m_hlight(), "START") != NULL)
|
||||||
|
send_cmd(KEY_PDA_SELECT);
|
||||||
|
else {
|
||||||
|
logMessage(LOG_ERR, "Error finding BOOST START menu\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
// Should be select options PAUSE | RESTART | STOP
|
||||||
|
int i=0;
|
||||||
|
for (i=0; i < 6; i++) {
|
||||||
|
send_cmd(KEY_PDA_DOWN);
|
||||||
|
waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,10);
|
||||||
|
if (strstr(pda_m_hlight(), "STOP") != NULL) {
|
||||||
|
send_cmd(KEY_PDA_SELECT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= 6)
|
||||||
|
logMessage(LOG_ERR, "Error finding BOOST STOP menu\n");
|
||||||
|
// Should be select options PAUSE | RESTART | STOP
|
||||||
|
// so press down twice then select
|
||||||
|
*/
|
||||||
|
// NSF This is really crap, but can't get above to work, need to come back and check menu items against selections.
|
||||||
|
send_cmd(KEY_PDA_DOWN);
|
||||||
|
send_cmd(KEY_PDA_DOWN);
|
||||||
|
send_cmd(KEY_PDA_SELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool set_PDA_aqualink_heater_setpoint(struct aqualinkdata *aq_data, int val, bool isPool) {
|
bool set_PDA_aqualink_heater_setpoint(struct aqualinkdata *aq_data, int val, bool isPool) {
|
||||||
char label[10];
|
char label[10];
|
||||||
int *cur_val;
|
int *cur_val;
|
||||||
|
|
|
@ -20,6 +20,8 @@ bool get_PDA_freeze_protect_temp(struct aqualinkdata *aq_data);
|
||||||
|
|
||||||
bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data);
|
bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data);
|
||||||
|
|
||||||
|
bool set_PDA_aqualink_boost(struct aqualinkdata *aq_data, bool val);
|
||||||
|
|
||||||
//void pda_programming_thread_check(struct aqualinkdata *aq_data);
|
//void pda_programming_thread_check(struct aqualinkdata *aq_data);
|
||||||
|
|
||||||
#endif // AQ_PDA_PROGRAMMER_H_
|
#endif // AQ_PDA_PROGRAMMER_H_
|
18
pda_menu.c
18
pda_menu.c
|
@ -61,6 +61,7 @@ char *pda_m_line(int index)
|
||||||
// return NULL;
|
// return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find exact menu item
|
||||||
int pda_find_m_index(char *text)
|
int pda_find_m_index(char *text)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -73,6 +74,7 @@ int pda_find_m_index(char *text)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fine menu item case insensative
|
||||||
int pda_find_m_index_case(char *text, int limit)
|
int pda_find_m_index_case(char *text, int limit)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -85,6 +87,20 @@ int pda_find_m_index_case(char *text, int limit)
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find menu item very loose
|
||||||
|
int pda_find_m_index_loose(char *text)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < PDA_LINES; i++) {
|
||||||
|
//printf ("+++ Compare '%s' to '%s' index %d\n",text,pda_m_line(i),i);
|
||||||
|
if (strstr(pda_m_line(i), text) != NULL)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
// Same as above but strip whitespace from menu item (NOT text parameter)
|
// Same as above but strip whitespace from menu item (NOT text parameter)
|
||||||
int pda_find_m_index_swcase(char *text, int limit)
|
int pda_find_m_index_swcase(char *text, int limit)
|
||||||
|
@ -148,6 +164,8 @@ pda_menu_type pda_m_type()
|
||||||
} else if (strncasecmp(_menu[0]," LABEL AUX", 12) == 0 && // Will have number ie AUX4
|
} else if (strncasecmp(_menu[0]," LABEL AUX", 12) == 0 && // Will have number ie AUX4
|
||||||
strncasecmp(_menu[2]," CURRENT LABEL ", 16) == 0) {
|
strncasecmp(_menu[2]," CURRENT LABEL ", 16) == 0) {
|
||||||
return PM_AUX_LABEL_DEVICE;
|
return PM_AUX_LABEL_DEVICE;
|
||||||
|
} else if (strstr(_menu[0],"BOOST")) { // This is bad check, but PDA menus are BOOST | BOOST POOL | BOOST SPA, need to do better.
|
||||||
|
return PM_BOOST;
|
||||||
}
|
}
|
||||||
return PM_UNKNOWN;
|
return PM_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ typedef enum pda_menu_type {
|
||||||
PM_SETTINGS,
|
PM_SETTINGS,
|
||||||
PM_EQUIPTMENT_CONTROL,
|
PM_EQUIPTMENT_CONTROL,
|
||||||
PM_EQUIPTMENT_STATUS,
|
PM_EQUIPTMENT_STATUS,
|
||||||
PM_PALM_OPTIONS // This seems to be only older revisions
|
PM_PALM_OPTIONS, // This seems to be only older revisions
|
||||||
|
PM_BOOST
|
||||||
} pda_menu_type;
|
} pda_menu_type;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -74,6 +75,7 @@ char *pda_m_line(int index);
|
||||||
pda_menu_type pda_m_type();
|
pda_menu_type pda_m_type();
|
||||||
int pda_find_m_index(char *text);
|
int pda_find_m_index(char *text);
|
||||||
int pda_find_m_index_case(char *text, int limit);
|
int pda_find_m_index_case(char *text, int limit);
|
||||||
|
int pda_find_m_index_loose(char *text);
|
||||||
//int pda_find_m_index_swcase(char *text, int limit);
|
//int pda_find_m_index_swcase(char *text, int limit);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -315,7 +315,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//packet_length = get_packet(rs_fd, packet_buffer);
|
//packet_length = get_packet(rs_fd, packet_buffer);
|
||||||
packet_length = get_packet_new(rs_fd, packet_buffer);
|
packet_length = get_packet(rs_fd, packet_buffer);
|
||||||
|
|
||||||
if (packet_length == -1) {
|
if (packet_length == -1) {
|
||||||
// Unrecoverable read error. Force an attempt to reconnect.
|
// Unrecoverable read error. Force an attempt to reconnect.
|
||||||
|
|
Loading…
Reference in New Issue