diff --git a/compiled/lighthub21/firmware.bin b/compiled/lighthub21/firmware.bin index c8f4a87..1cccf18 100644 Binary files a/compiled/lighthub21/firmware.bin and b/compiled/lighthub21/firmware.bin differ diff --git a/compiled/lighthub21/unlock.bat b/compiled/lighthub21/unlock.bat new file mode 100644 index 0000000..b0a2a9d --- /dev/null +++ b/compiled/lighthub21/unlock.bat @@ -0,0 +1,91 @@ +@ECHO off + +REM Wait X second for memory on Arduino Due is erased. +SET WAIT_ERASED=4 + +ECHO ------ External tool BossacArduinoDue started ------ + +REM number of command line arguments ok? +REM IF [%1]==[] GOTO error_args +REM IF [%2]==[] GOTO error_args + +REM set command line arguments +SET BOSSACPATH=..\tools\win\tool-bossac\bossac.exe +SET BINFILE=firmware.bin + +REM parse command line arguments +SET BOSSACPATH=%BOSSACPATH:"=% +SET BINFILE=%BINFILE:"=% + +REM workeround for bug in Atmel Studio 6.0.1996 Service Pack 2 +SET BINFILE=%BINFILE:\\=\% +SET BINFILE=%BINFILE:.cproj=% + +REM bossac path exist? +IF NOT EXIST "%BOSSACPATH%" GOTO error_arg1 + +REM bin file exist? +IF NOT EXIST "%BINFILE%" GOTO error_binfile + +REM fetch DeviceID of Arduino Due Programming Port from WMI Service +FOR /f "tokens=* skip=1" %%a IN ('wmic PATH Win32_SerialPort Where "Caption LIKE '%%BOSSA%%'" get DeviceID') DO ( + SET COMX=%%a + GOTO exit1 +) + +REM Arduino Due Programming Port not exist +GOTO error_comport + +:exit1 + +REM remove blank +SET COMPORT=%COMX: =% + +REM report in Atmel Studio 6.0 IDE output window +ECHO BossacPath=%BOSSACPATH% +ECHO BinFile=%BINFILE% +ECHO Arduino Due Programming Port is detected as %COMPORT%. + +REM The bossac bootloader only runs if the memory on Arduino Due is erased. +REM The Arduino IDE does this by opening and closing the COM port at 1200 baud. +REM This causes the Due to execute a soft erase command. +ECHO Forcing reset using 1200bps open/close on port +ECHO MODE %COMPORT%:1200,N,8,1 +MODE %COMPORT%:1200,N,8,1 + +REM Wait X second for memory on Arduino Due is erased. +ECHO Wait for memory on Arduino Due is erased... +PING -n %WAIT_ERASED% 127.0.0.1>NUL + +REM Execute bossac.exe +ECHO Execute bossac with command line: + +"%BOSSACPATH%" -i --port=%COMPORT% --unlock -R +REM START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -u -e -w -v -b "%BINFILE%" -R + +GOTO end + +:error_args +ECHO Error: wrong number of command line arguments passed! +GOTO end + +:error_arg1 +ECHO Error: command line argument 1 - path to bossac.exe not exist! - "C:\Program Files (x86)\arduino-1.5.2\hardware\tools\bossac.exe" +ECHO Error: command line argument 1 - argument passed = %1 +GOTO end + +:error_arg2 +ECHO Error: command line argument 2 - path to bin file not exist! - use $(OutputDirectory)\$(OutputFileName).bin +ECHO Error: command line argument 2 - argument passed = %1 +GOTO end + +:error_binfile +ECHO Error: bin file "%BINFILE%" not exist! +GOTO end + +:error_comport +ECHO Error: Arduino Due Programming Port not found! + +:end + +ECHO ======================== Done ======================== \ No newline at end of file diff --git a/compiled/lighthub21/upload.bat b/compiled/lighthub21/upload.bat index bdc64ae..49098ce 100644 --- a/compiled/lighthub21/upload.bat +++ b/compiled/lighthub21/upload.bat @@ -59,7 +59,7 @@ PING -n %WAIT_ERASED% 127.0.0.1>NUL REM Execute bossac.exe ECHO Execute bossac with command line: -"%BOSSACPATH%" -i --port=%COMPORT% -U false -e -u -w -v -b "%BINFILE%" -R +"%BOSSACPATH%" -i --port=%COMPORT% -U false -w -v -b "%BINFILE%" -R REM START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -U false -e -w -v -b "%BINFILE%" -R GOTO end diff --git a/compiled/lighthub21/uploadNative.bat b/compiled/lighthub21/uploadNative.bat index def9a70..7d92b87 100644 --- a/compiled/lighthub21/uploadNative.bat +++ b/compiled/lighthub21/uploadNative.bat @@ -60,7 +60,7 @@ PING -n %WAIT_ERASED% 127.0.0.1>NUL REM Execute bossac.exe ECHO Execute bossac with command line: -"%BOSSACPATH%" -i --port=%COMPORT% -u -e -w -v -b "%BINFILE%" -R +"%BOSSACPATH%" -i --port=%COMPORT% -w -v -b "%BINFILE%" -R REM START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -u -e -w -v -b "%BINFILE%" -R GOTO end diff --git a/lighthub/modules/out_ac.cpp b/lighthub/modules/out_ac.cpp index b1e8d81..c050e8a 100644 --- a/lighthub/modules/out_ac.cpp +++ b/lighthub/modules/out_ac.cpp @@ -19,21 +19,14 @@ extern bool disableCMD; #define INTERVAL_AC_POLLING 5000L -//static int driverStatus = CST_UNKNOWN; +#define AC_FAILED 15 +#define AC_UNKNOWN CST_UNKNOWN +#define AC_IDLE CST_INITIALIZED +#define AC_SENDING 2 -static int fresh =0; -static int power = 0; -static int swing =0; -static int lock_rem =0; -static int cur_tmp = 0; -static int set_tmp = 0; -static int fan_spd = 0; -static int mode = 0; - -long prevPolling = 0; byte inCheck = 0; byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса -byte data[37] = {}; //Массив данных + byte on[] = {255,255,10,0,0,0,0,0,1,1,77,2,91}; // Включение кондиционера byte off[] = {255,255,10,0,0,0,0,0,1,1,77,3,92}; // Выключение кондиционера byte lock[] = {255,255,10,0,0,0,0,0,1,3,0,0,14}; // Блокировка пульта @@ -45,7 +38,10 @@ const char SWING_P[] PROGMEM = "swing"; const char RAW_P[] PROGMEM = "raw"; void out_AC::getConfig(){ + ACSerial=&AC_Serial; + if (!item) return; + if (item->getArgCount()) switch(portNum=item->getArg(0)){ @@ -72,14 +68,24 @@ void out_AC::getConfig(){ void out_AC::InsertData(byte data[], size_t size){ + int fresh =0; + + int swing =0; + int lock_rem =0; + int cur_tmp = 0; + int set_tmp = 0; + int fan_spd = 0; + + char s_mode[10]; + set_tmp = data[B_SET_TMP]+16; if (set_tmp>40 || set_tmp<16) return; cur_tmp = data[B_CUR_TMP]; - mode = data[B_MODE]; + store->mode = data[B_MODE]; fan_spd = data[B_FAN_SPD]; swing = data[B_SWING]; - power = data[B_POWER]; + store->power = data[B_POWER]; lock_rem = data[B_LOCK_REM]; fresh = data[B_FRESH]; ///////////////////////////////// @@ -104,15 +110,15 @@ void out_AC::InsertData(byte data[], size_t size){ } */ - debugSerial.print ("Power="); - debugSerial.println(power); + debugSerial.print ("AC: Power="); + debugSerial.println(store->power); - if (power & 0x08) + if (store->power & 0x08) publishTopic(item->itemArr->name, "ON", "/quiet"); else publishTopic(item->itemArr->name, "OFF" , "/quiet"); - if (power & 0x02) //Compressor on + if (store->power & 0x02) //Compressor on publishTopic(item->itemArr->name, "ON","/compressor"); else publishTopic(item->itemArr->name, "OFF","/compressor"); @@ -155,28 +161,28 @@ void out_AC::InsertData(byte data[], size_t size){ //////////////////////////////////// s_mode[0]='\0'; - if (mode == 0x00){ + if (store->mode == 0x00){ strcpy_P(s_mode,AUTO_P); } - else if (mode == 0x01){ + else if (store->mode == 0x01){ strcpy_P(s_mode,COOL_P); } - else if (mode == 0x02){ + else if (store->mode == 0x02){ strcpy_P(s_mode,HEAT_P); } - else if (mode == 0x03){ + else if (store->mode == 0x03){ strcpy_P(s_mode,FAN_ONLY_P); } - else if (mode == 0x04){ + else if (store->mode == 0x04){ strcpy_P(s_mode,DRY_P); } - else if (mode == 109){ + else if (store->mode == 109){ strcpy_P(s_mode,ERROR_P); } - publishTopic(item->itemArr->name, (long) mode, "/mode"); + publishTopic(item->itemArr->name, (long) store->mode, "/mode"); - if (power & 0x01) + if (store->power & 0x01) publishTopic(item->itemArr->name, s_mode,"/cmd"); else publishTopic(item->itemArr->name, "OFF","/cmd"); @@ -208,11 +214,17 @@ byte getCRC(byte req[], size_t size){ } void out_AC::SendData(byte req[], size_t size){ +if (!store || !item) return; +if (item->itemArr->subtype == AC_SENDING) + { + while (store->timestamp && !isTimeOver(store->timestamp,millis(),150)) yield(); + } + ACSerial->write(req, size - 1); ACSerial->write(getCRC(req, size-1)); //ACSerial->flush(); - item->setExt(millisNZ()); - debugSerial<timestamp=millisNZ(); + debugSerial<itemArr->subtype = AC_SENDING; } inline unsigned char toHex( char ch ){ @@ -238,19 +250,32 @@ int out_AC::Setup() { abstractOut::Setup(); if (!item) return 0; -debugSerial<setPersistent(new acPersistent); +if (!store) + { errorSerial<data,0,sizeof(acPersistent::data)); +store->mode=0; +store->power=0; +store->inCheck=0; +store->timestamp=millisNZ(); + if (!portNum)// && (g_APinDescription[0].ulPinType == PIO_PA8A_URXD)) { pinMode(0, INPUT_PULLUP); #if debugSerial == Serial - infoSerial<begin(9600); -item->itemArr->subtype = CST_INITIALIZED; +item->itemArr->subtype = AC_IDLE; + //driverStatus = CST_INITIALIZED; return 1; } @@ -258,7 +283,10 @@ return 1; int out_AC::Stop() { if (!item) return 0; -debugSerial<setPersistent(NULL); +store = NULL; item->itemArr->subtype = CST_UNKNOWN; return 1; } @@ -266,49 +294,72 @@ return 1; int out_AC::Status() { if (!item) return 0; -return item->itemArr->subtype; +switch (item->itemArr->subtype) +{ +case AC_FAILED: return CST_FAILED; +case AC_UNKNOWN: return CST_UNKNOWN; +default: +return CST_INITIALIZED; +//return item->itemArr->subtype; +} } - int out_AC::isActive() { -return (power & 1); +if (!store) return 0; +return (store->power & 1); } int out_AC::Poll(short cause) { +if (!store) return -1; + +switch (item->itemArr->subtype) +{ +case AC_FAILED: return -1; +case AC_UNKNOWN: return -1; +case AC_SENDING: + { + if (store->timestamp && isTimeOver(store->timestamp,millis(),150)) + { + item->itemArr->subtype = AC_IDLE; + store->timestamp=millisNZ(); + } + } +} + if (cause!=POLLING_SLOW) return false; - if (isTimeOver(prevPolling,millis(),INTERVAL_AC_POLLING)) { - prevPolling = millisNZ(); - debugSerial.println(F("Polling")); + if ((item->itemArr->subtype == AC_IDLE) && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING)) + { + debugSerial.println(F("AC: Polling")); SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера } if(ACSerial->available() >= 37){ //was 0 - ACSerial->readBytes(data, 37); + ACSerial->readBytes(store->data, 37); while(ACSerial->available()){ delay(2); ACSerial->read(); } -debugSerial<> "); +debugSerial<> "); for (int i=0; i < 37-1; i++) { - if (data[i] < 10){ + if (store->data[i] < 10){ debugSerial.print("0"); - debugSerial.print(data[i], HEX); + debugSerial.print(store->data[i], HEX); } else { - debugSerial.print(data[i], HEX); + debugSerial.print(store->data[i], HEX); } } - if (data[36] != inCheck){ - inCheck = data[36]; - InsertData(data, 37); - debugSerial<data[36] != store->inCheck){ + store->inCheck = store->data[36]; + InsertData(store->data, 37); + debugSerial<= 16 && set_tmp <= 40) { //if (set_tmp>40 || set_tmp<16) set_temp=21; - data[B_SET_TMP] = set_tmp -16; + store->data[B_SET_TMP] = set_tmp -16; publishTopic(item->itemArr->name,(long) set_tmp,"/set"); } - else return -1; + else return -1; + } break; case S_CMD: @@ -351,52 +404,52 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) { case CMD_ON: case CMD_XON: - data[B_POWER] = power; - data[B_POWER] |= 1; + store->data[B_POWER] = store->power; + store->data[B_POWER] |= 1; SendData(on, sizeof(on)/sizeof(byte)); // publishTopic(item->itemArr->name,"ON","/cmd"); return 1; break; case CMD_OFF: case CMD_HALT: - data[B_POWER] = power; - data[B_POWER] &= ~1; + store->data[B_POWER] = store->power; + store->data[B_POWER] &= ~1; SendData(off, sizeof(off)/sizeof(byte)); // publishTopic(item->itemArr->name,"OFF","/cmd"); return 1; break; case CMD_AUTO: - data[B_MODE] = 0; - data[B_POWER] = power; - data[B_POWER] |= 1; + store->data[B_MODE] = 0; + store->data[B_POWER] = store->power; + store->data[B_POWER] |= 1; // strcpy_P(s_mode,AUTO_P); break; case CMD_COOL: - data[B_MODE] = 1; - data[B_POWER] = power; - data[B_POWER] |= 1; + store->data[B_MODE] = 1; + store->data[B_POWER] = store->power; + store->data[B_POWER] |= 1; // strcpy_P(s_mode,COOL_P); break; case CMD_HEAT: - data[B_MODE] = 2; - data[B_POWER] = power; - data[B_POWER] |= 1; + store->data[B_MODE] = 2; + store->data[B_POWER] = store->power; + store->data[B_POWER] |= 1; // strcpy_P(s_mode,HEAT_P); break; case CMD_DRY: - data[B_MODE] = 4; - data[B_POWER] = power; - data[B_POWER] |= 1; + store->data[B_MODE] = 4; + store->data[B_POWER] = store->power; + store->data[B_POWER] |= 1; // strcpy_P(s_mode,DRY_P); break; case CMD_FAN: - data[B_MODE] = 3; + store->data[B_MODE] = 3; // debugSerial<<"fan\n"; - data[B_POWER] = power; - data[B_POWER] |= 1; - if (data[B_FAN_SPD] == 3) + store->data[B_POWER] = store->power; + store->data[B_POWER] |= 1; + if (store->data[B_FAN_SPD] == 3) { - data[B_FAN_SPD] = 2; //Auto - fan speed in Ventilation mode not working + store->data[B_FAN_SPD] = 2; //Auto - fan speed in Ventilation mode not working } // strcpy_P(s_mode,FAN_ONLY_P); break; @@ -413,24 +466,24 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) switch (cmd.getCmd()) { case CMD_AUTO: - data[B_FAN_SPD] = 3; + store->data[B_FAN_SPD] = 3; strcpy_P(s_speed,AUTO_P); break; case CMD_HIGH: - data[B_FAN_SPD] = 0; + store->data[B_FAN_SPD] = 0; strcpy_P(s_speed,HIGH_P); break; case CMD_MED: - data[B_FAN_SPD] = 1; + store->data[B_FAN_SPD] = 1; strcpy_P(s_speed,MED_P); break; case CMD_LOW: - data[B_FAN_SPD] = 2; + store->data[B_FAN_SPD] = 2; strcpy_P(s_speed,LOW_P); break; default: //if (n) data[B_FAN_SPD] = Parameters[0]; - data[B_FAN_SPD] = cmd.getInt(); + store->data[B_FAN_SPD] = cmd.getInt(); //TODO - mapping digits to speed } publishTopic(item->itemArr->name,s_speed,"/fan"); @@ -438,17 +491,17 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) case S_MODE: //data[B_MODE] = Parameters[0]; - data[B_MODE] = cmd.getInt(); + store->data[B_MODE] = cmd.getInt(); break; case S_LOCK: switch (cmd.getCmd()) { case CMD_ON: - data[B_LOCK_REM] = 80; + store->data[B_LOCK_REM] = 80; break; case CMD_OFF: - data[B_LOCK_REM] = 0; + store->data[B_LOCK_REM] = 0; break; } break; @@ -457,16 +510,16 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) switch (cmd.getCmd()) { case CMD_ON: - data[B_SWING] = 3; + store->data[B_SWING] = 3; publishTopic(item->itemArr->name,"ON","/swing"); break; case CMD_OFF: - data[B_SWING] = 0; + store->data[B_SWING] = 0; publishTopic(item->itemArr->name,"OFF","/swing"); break; default: //if (n) data[B_SWING] = Parameters[0]; - data[B_SWING] = cmd.getInt(); + store->data[B_SWING] = cmd.getInt(); } break; @@ -475,10 +528,10 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) switch (cmd.getCmd()) { case CMD_ON: - data[B_POWER] |= 8; + store->data[B_POWER] |= 8; break; case CMD_OFF: - data[B_POWER] &= ~8; + store->data[B_POWER] &= ~8; break; } @@ -532,14 +585,16 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) //if (strTopic == "/myhome/in/Conditioner/RAW") - data[B_CMD] = 0; - data[9] = 1; - data[10] = 77; - data[11] = 95; - ACSerial->flush(); - uint32_t ts=item->getExt(); - while (ts && !isTimeOver(ts,millis(),100)) yield(); - SendData(data, sizeof(data)/sizeof(byte)); + store->data[B_CMD] = 0; + store->data[9] = 1; + store->data[10] = 77; + store->data[11] = 95; + + ///ACSerial->flush(); + + //uint32_t ts=item->getExt(); + //while (ts && !isTimeOver(ts,millis(),100)) yield(); + SendData(store->data, sizeof(store->data)/sizeof(byte)); //InsertData(data, sizeof(data)/sizeof(byte)); //ACSerial->flush(); //item->setExt(millisNZ()); diff --git a/lighthub/modules/out_ac.h b/lighthub/modules/out_ac.h index 5035f95..c6a72bd 100644 --- a/lighthub/modules/out_ac.h +++ b/lighthub/modules/out_ac.h @@ -2,6 +2,7 @@ #pragma once #ifndef AC_DISABLE #include +#include #include "itemCmd.h" #define LEN_B 37 @@ -21,10 +22,20 @@ //#define S_RAW S_ADDITIONAL+4 extern void modbusIdle(void) ; + +class acPersistent : public chPersistent { +public: + byte data[37]; + byte power; + byte mode; + byte inCheck; + uint32_t timestamp; +}; + class out_AC : public abstractOut { public: - out_AC(Item * _item):abstractOut(_item){getConfig();}; + out_AC(Item * _item):abstractOut(_item){store = (acPersistent *) item->getPersistent(); getConfig();}; void getConfig(); int Setup() override; int Poll(short cause) override; @@ -36,6 +47,7 @@ public: int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override; protected: + acPersistent * store; void InsertData(byte data[], size_t size); void SendData(byte req[], size_t size); uint8_t portNum;